find

find 명령어는 리눅스를 사용함에 있어서 아주 유용한 기능을 제공해주는 명령어입니다. 말 그대로 우리가 원하는 파일이나 디렉토리를 찾아줍니다. 윈도우로 따진다면 아래의 입력란이 되겠지요.

윈도즈에서는 아래에 파일명을 치면 검색이 가능하지만 리눅스에서는 find라는 명령어를 통해서 파일을 찾을 수 있습니다. 잘만 사용하면 너무나 편리한 명령어이기도 합니다.

하지만 find명령은 너무나 사용하기에 광범위한 명령어이므로 그 중 자주 사용되는 몇가지만 소개하도록 하겠습니다.

 

이제부터 find 명령을 통해서 어떻게 파일을 찾을 수 있을지 알아보겠습니다.

 

1) 기본적인 파일 찾기

find는 기본적으로 찾을 파일 경로와 이름으로 구성되면 정말 그 파일만 찾는 기능을 할 수 있습니다. 아래 처럼 말이지요.

#find /home -name "test.c" 

설명

/home : 파일을 찾을 디렉토리를 지칭합니다.

-name "test.c" : test.c 파일을 찾습니다. 

 

결과

/home/centos/code/test.c
/home/centos/test.c

 

2) 와일드카드(*)를 이용한 단어를 포함한 파일 찾기

find 명령어는 파일이름에 와일드카드 문자(*)를 포함하여 특정 단어를 포함하는 파일을 찾을 수 있습니다.

#find /home -name "*test*"

설명

/home : 파일을 찾을 디렉토리입니다.

-name "*test*" : test라는 단어를 포함하는 파일을 찾습니다. ttest이든, test.c이든, aatestbb 파일이든 전부 찾아줍니다.

 

결과

/home/centos/code/test.c
/home/centos/test.c
/home/centos/patience_test.c

 

3) -type 옵션으로 파일의 타입을 포함하여 찾기

저는 test라는 디렉터리를 하나 만들었고 여기서 test라는 단어를 포함하는 디렉터리를 찾아보도록 하겠습니다.

/home/centos/code/test.c
/home/centos/test.c
/home/centos/patience_test.c
/home/centos/test <- directory
#find /home -name "*test*" -type d

설명 

-type d : 파일 type이 디렉터리인것만 찾습니다.

 

결과

/home/centos/test

파일 타입은 다음과 같습니다.

option type
f regular file
d directory
c character special
b block special
l symbolic link
s socket
p fifo

 

4) 파일의 크기에 따른 파일 검색

-size 옵션으로 파일의 크기를 검색할 수 있습니다. 파일 크기 앞에 '+'를 붙이면 그 크기 초과, '-'를 붙이면 그 크기 미만으로 검색이 됩니다. 또한 파일 크기 뒤에 단위가 붙는데요. 아래와 같습니다. 단위를 생략하면 기본적으로 리눅스 블록(b)이 단위가 됩니다.

(b:block, c:bytes, w:2bytes, k:kbytes, M:mbytes, G:gbytes)

옵션 단위
c 1byte 단위
b 1block 단위(1block = 512 bytes)
w 2 bytes 단위
k 1 kilobytes
M 1 metabytes
G 1 gigabytes

몇 가지 예제)

find /home -size 1k 크기가 1k인 파일 검색
find /home -size +100M 100M 초과인 파일 검색
find /home -size -1G 1G 미만인 파일 검색
find /home -size +100M -size -2G 100M 초과 2G 미만인 파일 검색

 

 

5) exec으로 찾을 파일에 명령어 실행

-exec으로 명령어를 실행할 수 있습니다.

find명령을 통한 파일들은 모두 {}에 담겨지게 됩니다. 그러니까 ls -al {} 또는 ls {} -al 인 것이고, cp {} . 인것이 왜인지 생각해보세요.

ls -al {파일}, 또는 ls {파일} -al은 같은 결과를 갖습니다. 전달받는 파일 인자는 1개이니까요 .

반대로 cp는 2개의 파일 인자를 받습니다. 첫번째 인자는 복사가 될 파일, 두번째 인자는 복사가 될 위치이지요. 그래서 cp {파일} . 가 됩니다.

명령어 끝은 항상 \;으로 끝나야합니다. 프로그래밍을 하는 분이라면 ;이 연산의 종료를 의미한다는 것을 아실겁니다. ';'은 특수문자이기 때문에 escape(특수문자화 하지 않는 것)하기 위해 \를 같이 사용합니다. 이해가 안된다면 그냥 외우시거나 프로그래밍 언어를 배우시는 것을 추천드립니다. ㅎㅎㅎ 

 

예제를 통해서 살피도록 하겠습니다.

 

예제 1) 

find /home -name "*test*" -exec ls -al {} \;

설명

test라는 단어가 포함된 파일을 대상으로 ls -al을 실행합니다. {}의 위치를 잘봐두세요.

 

결과

-rw-r--r--. 1 root root 313  2월 29 02:37 /home/centos/code/test.c
-rw-r--r--. 1 root root 0  3월  3 06:57 /home/centos/test.c
-rw-r--r--. 1 root root 0  3월  3 07:04 /home/centos/patience_test.c
합계 4
drwxr-xr-x.  2 root   root      6  3월  3 07:08 .
drwx------. 17 centos centos 4096  3월  3 07:34 ..

 

예제 2)

find /bin/ -name "*gr*" -exec cp {} /home/centos  \;

설명

bin 하위의 gr이라는 파일이나 디렉토리를 복사해 /home/centos로 위치합니다. 실제 실행하고 나서 /home/centos에 위치하여 결과를 보면 이런 파일들이 존재합니다.

 

결과

bzegrep            groff                  grub2-mkstandalone  xzfgrep
bzfgrep            grops                  grub2-script-check  xzgrep
bzgrep             grotty                 grub2-syslinux2cfg  zegrep
chgrp              groups                 lexgrog             zfgrep

..생략..

이뿐만 아니라 rm, mv 등의 명령도 실행 가능합니다. rm은 쓸때 꼭 주의하세요.

 

예제 3)

아까 옮겼던 gr이 포함된 단어의 파일들을 전부 삭제해보도록 하겠습니다.(우선 그전에 gr이 포함된 파일 중 원래 그 자리에 있었던 파일이 있는지 확인하세요.)

find /home/centos/ -name "*gr*" -exec rm -rf {} \;

설명

찾은 파일에 대해서 강제 삭제 명령(rm -rf)을 하게 됩니다. 이 명령어는 전달되는 파일이 하나밖에 없으므로 {}이 어디에나 위치해도 됩니다. rm -rf {} 이건 rm {} -rf이건 상관이 없다 이거죠. 허나 반드시 이 명령어를 실행하지 마시기바랍니다. 잘못하면 진짜 ㅈ돼요.

 

결과

gr이 포함된 모든 파일이 삭제되었습니다.

 

6) 특정 단어 또는 내용을 갖는 파일을 검색하기

끝에 파이프를 연결해서 | xargs grep "검색할 내용"을 덧붙이면 되는데 에러 또는 경고까지 전부 출력하므로 에러(2)는 전부 쓰레기통(/dev/null)에 버려 출력하지 않게 합시다.

find / -name "*.c*" -type f | xargs grep "#include" 2>/dev/null

설명

/디렉토리부터 확장자가 c를 포함하며 파일은 정규파일을 검색합니다.  그때 #include라는 문자열을 포함하는 파일만 검색하며 오류 출력은 전부 쓰레기통인 /dev/null로 갖다 버립니다.

 

결과

뭐 이런것들이 보이네요.

/usr/lib/firmware/isci/create_fw.c:#include 
/usr/lib/firmware/isci/create_fw.c:#include 
/usr/lib/firmware/isci/create_fw.c:#include 
/usr/lib/firmware/isci/create_fw.c:#include <sys/types.h>
/usr/lib/firmware/isci/create_fw.c:#include <sys/stat.h>
/usr/lib/firmware/isci/create_fw.c:#include 
/usr/lib/firmware/isci/create_fw.c:#include 
/usr/lib/firmware/isci/create_fw.c:#include 
/usr/lib/firmware/isci/create_fw.c:#include <asm/types.h>
/usr/lib/firmware/isci/create_fw.c:#include 

... 생략 ...

 

 

 

7) 특정 권한을 갖는 파일 찾기

-perm 옵션으로 어떤 파일이 어떤 권한이 있는지 검색할 수 있습니다. 

find . -perm 777

설명

위의 명렁은 유저 권한으로 읽기, 쓰기 , 실행 그리고 그룹 권한으로 읽기, 쓰기, 실행 마지막으로 다른 유저 권한으로는 읽기, 쓰기, 실행 권한인 파일을 모조리 찾는 명령어입니다.

만일 -perm 644라면 유저 권한으로 읽기,쓰기 그룹 권한으로 읽기, 다른 유저 권한으로 읽기의 파일들을 전부 찾습니다.

 

8) 끝까지 찾지 않아도 되는 maxdepth

maxdepth는 찾는 깊이를 뜻합니다. find명령어는 기본적으로 지정된 디렉토리 밑으로 끝까지 search합니다. 만약 maxdepth 옵션을 준다면 지정된 깊이까지만 파일을 검색합니다. 깊이라함은 하위디렉토리를 뜻합니다.

maxdepth의 0은 자기 자신을 의미합니다.

 find / -maxdepth 1

설명

/디렉토리에서 깊이가 1인 파일들만 검색합니다. 결과는 다음과 같습니다.

 

결과

/
/dev
/proc
/run
/swap
/sys
/etc
/root
/var
/usr
/bin
/sbin
/lib
/lib64
/boot
/home
/media
/mnt
/opt
/srv
/tmp

 

지금까지 제가 현업에서 자주 사용하는 find명령어의 옵션을 살펴보았는데요. 가만히보면 이외의 명령어를 사용할 일이 별로 없었습니다. 다른 분들은 잘 모르겠네요. 

 

기능도 막강하고 배우기에는 너무 범위가 넓은 find 명령어는 알면 알 수록 흥미있는 명령어인것 같습니다. 제가 모르거나 놓친 부분이거나, 또는 많이 사용하지만 이곳에 나오지 않은 옵션이라면 댓글 달아주세요!

 

나머지 기능은 꾸준히 업데이트하여 올리도록 하겠습니다.

 

 

반응형
블로그 이미지

REAKWON

와나진짜

,

UDP(User Datagram Protocol)

TCP가 신뢰성에 기반을 둔 전송 계층 프로토콜이라면 UDP는 빠른 데이터 전송 위주의 프로토콜입니다. 속도를 떨어뜨리는 요소를 없애 TCP처럼 각종 흐름제어, 오류제어, 혼잡 제어를 하지 않습니다. 따라서 UDP는 비신뢰성(Unreliable) 프로토콜입니다.

 

이 UDP 프로토콜, 저와 같은 세대시라면 어디서 많이 보셨죠? 저는 뮤컨을 위해서 스타크래프트의 UDP는 필수였습니다. 이렇게 데이터는 그다지 중요하지 않으면서 속도가 빠른 데이터 전송이 필요할때 UDP를 사용합니다.

 

데이터 전송과정을 보게 되면 이렇습니다.

만일 송신에서 데이터를 1, 2, 3 순으로 전송했다고 할때 네트워크의 사용량에 따라 어떤 데이터그램은 늦게 도착할 수 있습니다. 3번 데이터그램이 가장 좋은 경로를 타고 와서 먼저 도착하게 됩니다. 그 이후에는 1번 데이터그램이 도착하겠네요. 마지막으로 가장 부하가 많은 경로를 타고 들어온 2번 데이터그램이 도착합니다. 

결국 수신자는 3, 1, 2 데이터그램 순으로 전달받게 됩니다. 연결과정 자체를 갖지 않기 때문에 데이터의 순서를 보장하지 않습니다.

 

 

 

헤더 정보(UDP Header)

빠른 전송을 요구할때 쓰이는 UDP는 헤더의 구조가 너무나 간단합니다. 헤더는 단 4가지 정보만 존재합니다.

 

UDP 헤더 정보

너무 간단합니다.

- Source Port : 송신지의 Port 번호입니다.

- Destination Port : 목적지의 Port 번호입니다.

- Total Length : 헤더를 포함한 전체 데이터그램의 크기를 의미하는 필드입니다.

- Checksum : 데이터그램의 오류를 확인하기 위한 필드입니다.

 

UDP 특징

UDP의 특징을 요약하면 다음과 같습니다.

1) TCP와 같이 연결을 성립하는 3-way-handshake와 같은 과정이 없습니다. 따라서 비연결형인 특징을 갖습니다. 연결을 확립하는 TCP는 회선을 연결한듯 정확한 연결을 요구하므로 가상회선 방식이라 하며 UDP는 그런 과정없이 데이터를 쪼개 보내므로 데이터그램 방식이라 합니다.

2) 따라서 데이터의 순서, 유실을 보장하지 않고, 데이터 수신 실패시 재전송을 요구하지 않습니다. 데이터를 수신할때 순서가 뒤바뀔 수도 있습니다. 이는 곧 비신뢰성을 의미합니다. 

3) 데이터를 일방적으로 수신받기 때문에 속도가 매우 빠릅니다.

4) 데이터의 checksum으로 최소한의 오류만을 검출합니다. 그러니까 받는 데이터는 검사를 하지만 유실된 데이터는 모른다는 것이지요.

 

 

반응형
블로그 이미지

REAKWON

와나진짜

,

 

 

TCP(Transmission Control Protocol)

IP 계층 위에서 동작하는 TCP는 연결 지향 프로토콜입니다. 마치 물리적인 선로로 연결되어 있는 것처럼 가상의 연결 통로를 설정하여 통신합니다. 그만큼 정확한 데이터 전송을 요구하며 신뢰성을 보장하기 때문에 신뢰할 수 있는 프로토콜(Reliable Protocol)이라고 합니다. 신뢰성 보장을 위해서 다음의 제어를 수행합니다. 

 

1) 흐름 제어(Flow Control)

데이터를 보내는 사람, 받는 사람이 있다고 할때 줄 수 있는 양, 받을 수 있는 양이 다릅니다. 그래서 상대방이 받을 수 있을 만큼의 양으로 적절히 전송하는 것을 흐름제어라고 합니다. 

 

2) 혼잡 제어(Congestion Control)

네트워크가 혼잡해지면 송신자가 데이터의 전송량을 제어하는 것을 뜻합니다. 혼잡하다라는 것을 어떻게 알 수 있을까요? 데이터의 손실 발생이 많아지면 이는 즉, 네트워크가 혼잡한 상태로 판단하여 전송량을 제어하게 됩니다.

 

3) 오류 제어(Error Control)

데이터의 오류나 손실없는 전송을 보장해주는 것이 혼잡 제어입니다. 오류 발생 시 TCP는 데이터를 제전송합니다.

 

 

 

 

 

TCP 헤더

TCP 프로토콜은 신뢰성을 보장하기 위해서 헤더에 많은 정보를 포함하게 되는데 각 필드에 어떤 정보를 포함하는지 알아보도록 하겠습니다.

TCP 프로토콜의 구조

 

- Source Port: 출발지의 포트, 즉 데이터를 보내는 컴퓨터의 포트 정보입니다. 컴퓨터가 갖을 수 있는 포트는 65536개이므로 사이즈가 2바이트인것을 확인하세요. 

 

- Destination Port: 반대로 목적지의 포트입니다. 

 

- Sequence Number : 송신 데이터의 일련 번호를 담고 있습니다. 

 

- Acknowledgement Number : 그전의 데이터를 잘 받았다는 표시로 상대방이 다음에 전송할 일련번호를 담고 있습니다. 줄여서 ACK라고 하겠습니다.

 

- HLEN(Header Length) : 헤더의 정보를 담고 있습니다. 4 bits의 워드 단위입니다. 헤더의 길이는 최소 20바이트 ~ 60바이트까지입니다.

 

- Reserved : 예약된 비트입니다. 아직 사용하지 않습니다. 나중을 위해서 남겨두는 비트인 셈이지요.

 

- Control Flags 

FLAG 설명

URG

(Urgent Pointer)

Urgent Pointer의 필드가 유요하다는 의미의 FLAG

ACK

(Acknowledgement)

수신 확인 응답 FLAG

PSH

(Request for push)

송수신 버퍼의 있는 데이터 즉시 처리 요청 FLAG

RST

(Reset the connection)

연결을 강제 중단합니다. TCP가 유지되고 있을때 이 FLAG를 사용하면 그 즉시 연결을 끊어 버립니다. 해커들이 Hijacking을 위해 피해자의 연결을 끊어버릴때 사용합니다. 보통의 정상적인 종료는 아래의 FIN FLAG를 설정합니다.

SYN

(Synchronize sequence number)

연결 설정 FLAG

FIN

(Terminate the connection)

정상 종료의 연결 종료 FLAG

 

- Window Size :  수신자에서 송신자로 보내는 수신자의 윈도우 사이즈입니다. 즉, 수신 버퍼의 여유공간 크기를 의미하게 되지요. 송신자는 이 윈도우 사이즈 범위 내에서 수신측의 수신 확인(ACK)을 확인하지 않고 연속적으로 데이터를 보낼 수 있습니다.

 

- Checksum : 오류를 검사하기 위한 필드입니다. 전체 데이터가 오류가 나 변형되었는지 확인합니다. 

 

- Urgent Pointer : 긴급 데이터의 위치값을 담고 있습니다. 

 

 

 

 

 

 

 

 

TCP의 연결 설정 과정(3-way handshake)

TCP연결은 어떻게 연결이 될까요? 3단계 절차에 따라서 연결이 성립됩니다. 이때 사용되는 FLAG는 2개입니다. 바로 SYN과 ACK입니다. 다음의 그림을 통해서 연결과정을 알아보도록 합시다.

 

3-way handshake

 

1. 최초 클라이언트 측에서 동기화를 위해 SYN FLAG와 함께 Seq(uence) Number를 임의로 설정해서 보내줍니다. 이때 최초의 Seq number를 ISN(Initial Sequence Number)라고 합니다.

아직 상대방에게서 데이터를 수신하지 않았으므로 Ack(nowledgement) Number 필드는 비어있네요. SYN 패킷을 보냈으므로 클라이언트의 상태는 SYN_SENT가 됩니다. 서버는 SYN을 받았으므로 SYN_RECV 상태 또는 SYN_RCVD상태가 됩니다.

 

이때 클라이언트가 적극적으로 연결 요청을 하고 있네요. 이것을 Active Open이라 합니다. 서버는 수동적으로 받아들이고 있네요. 이것을 Passive Open이라고 합니다.

 

2. 서버에서 동기화 요청을 받았으면 잘 받았으니 연결하자고 요청합니다. 클라이언트에서 보낸 Ack number에 받은 Seq에 +1을 하여 다음 Seq Number를 요구합니다. 클라이언트의 Seq number가 100이므로 101을 Ack number로 보내는 군요. 또한 자신도 역시 ISN을 설정하여 다시 클라이언트로 보냅니다. 

이때 사용한 플래그는 ACK와 SYN입니다. ACK와 SYN이 유요한 데이터이기 때문이죠. 이 페킷을 보낸 후 서버는 연결 확립(ESTABLISHED)상태가 됩니다. 

 

3. 클라이언트는 이에 대한 응답으로 서버에게 ACK num을 설정하여 보냅니다. 이 패킷을 준 후 클라이언트도 연결 확인 상태가 됩니다.

 

이렇게 보면 초기에 데이터가 왔다 갔다 3번하고 있죠? 이것을 3-Way Handshake라고 합니다.

 

아래는 실제 3 way handshake를 와이어샤크로 찍어본 화면입니다.

wire shark hand shake

 

 

연결 종료(4-way handshake)

정상적인 연결 종료는 FIN, ACK의 플래그를 통해서 이루어집니다. 아래와 같이 4단계를 거쳐 연결이 종료가 됩니다. 

1. 연결상태에 있던 클라언트가 연결을 종료하기 위해 FIN을 보냅니다. 이때 클라이언트의 상태는 FIN_WAIT_1 상태가 되고 서버는 CLOSE_WAIT 상태가 됩니다. 3 way handshake와 마찬가지로 먼저 close요청을 한쪽이 Active Close, 받은쪽이 Passive Close라고 합니다.

 

2. 수신하는 서버는 이에 대한 응답으로 ACK를 보냅니다. 이때 클라이언트는 FIN_WAIT_2의 상태가 됩니다.

 

3. 서버는 이 후 소켓을 받는 시스템 콜(close)을 호출할때까지 대기 상태로 있다가 소켓이 종료되면 FIN을 보냅니다. 마지막 FIN과 함께 ACK를 보냈으므로 LAST_ACK 상태가 됩니다.

 

4. 서버로부터 FIN을 받은 클라이언트는 ACK응답을 하여 2MSL만큼의 시간(보통 1분에서 4분)이후 연결 종료 상태(CLOSED)가 됩니다. 서버 CLOSED상태가 되어 연결이 종료됩니다.

 

이러한 과정을 4-way handshake로 연결이 정상적으로 연결이 종료되는 과정입니다.

 

 

반응형
블로그 이미지

REAKWON

와나진짜

,

소켓 통신에 대한 개념과 예제가 더 많은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

소켓(socket)

네트워크 통신을 하는 표준 방법으로 프로세스간 연결의 종점이라고 볼 수 있습니다. 기본적인 개념은 아래의 그림과 같습니다. 

위의 그림은 TCP/IP에서의 인터넷 통신을 보여줍니다. 클라이언트의 컴퓨터의 물리적 주소(MAC 주소) DD-44-EE-55-FF-66이며 논리적 주소(IP 주소)는 10.2.2.2입니다. 클라이언트는 여러가지의 프로그램을 실행시키고 있는데 그 중 어떤 프로세스는 TCP 포트번호 12345를 사용합니다. 이 클라이언트 프로세스는 물리적 주소가 11-AA-22-BB-33-CC이며 논리적 주소 10.1.1.3인 서버 컴퓨터의 포트 번호 80번을 사용하는 서버 프로세스와 연결되어 있습니다.

 

구체적으로 어떻게 통신할까요? 각 프로세스는 소켓을 통해서 통신을 하게 되는데, 소켓은 간단히 얘기해 ip주소와 포트번호를 갖고 있는 인터페이스라고 생각하면 됩니다. 소켓은 리눅스에서 파일로 다루어지며 프로세스는 이 소켓을 사용할때 파일디스크립터를 통해 사용합니다. 우리는 리눅스 파일 입출력에 대해 배울때 파일디스크립터를 사용했지요? 소켓 역시 파일디스크립터를 이용해서 읽기, 쓰기가 가능합니다.

 

소켓 통신할때 필요한 주요함수는 무엇이 있을까요? 간단히 알아보도록 합시다. 

 

1. socket(int domain, int type, int protocol)

소켓을 만드는데 바로 이 함수를 사용합니다. 소켓 역시 파일로 다루어지기 때문에 반환값은 파일디스크립터입니다. 만약 소켓을 여는데 실패했다면 -1을 리턴합니다.

 

2. connect(int fd, struct sockaddr *remote_host, socklen_t addr_length)

원격 호스트(원격 컴퓨터)와 연결하는 함수입니다. 연결된 정보는 remote_host에 저장됩니다. 성공시 0, 오류시 -1을 반환합니다.

 

3. bind(int fd, struct sockaddr *local_addr, socklen_t addr_length)

소켓을 바인딩합니다. 이렇게 생각하면 됩니다. 지금 fd로 넘겨지는 소켓과 이 프로세스와 묶는다(bind)라고 생각하시면 됩니다. 그래서 해당 프로세스는 소켓을 통해 다른 컴퓨터로부터 연결을 받아들일 수 있습니다.

 

4. listen(int fd, int backlog_queue_size)

소켓을 통해 들어오는 연결을 듣습니다. backlog_queue_size만큼 연결 요청을 큐에 넣습니다. 성공시 0, 오류시 -1을 반환합니다.

 

5. accept(int fd, sockaddr *remote_host, socklen_t *addr_length)

어떤 컴퓨터에서 이 컴퓨터로 연결할때 연결을 받아들입니다. 함수 이름이 말해주고 있죠.

연결된 원격 컴퓨터의 정보는 remote_host에 저장됩니다. 오류시에 -1을 반환합니다.

 

6. send(int fd, void* buffer, size_t n, int flags)

buffer를 소켓 파일 디스크립터인 fd로 전송합니다. 보낸 바이트수를 반환하며 실패시 -1을 반환합니다.

 

7. recv(int fd, void* buffer, size_t n, int flags)

send함수와 사용법이 거의 비슷합니다. n바이트를 buffer로 읽습니다. 성공시 받은 바이트수를 반환하며 실패시 -1을 반환합니다.

 

 

 

이제 예제를 보며 더 자세한 설명을 하도록 하죠. 다음 예제는 서버 프로그램이 클라이언트 프로그램에서 전송한 메시지를 출력해주는 소스코드입니다. 클라이언트 프로그램은 텔넷을 사용할 것이기 때문에 따로 클라이언트 프로그램 소스코드는 없습니다.

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 12346
#define BUF_SIZE 1024
int main(void){
        int socket_fd,accepted_fd;
        struct sockaddr_in host_addr, client_addr;
        socklen_t size;
        int recv_length;
        char buffer[BUF_SIZE];

        socket_fd=socket(PF_INET,SOCK_STREAM,0);

        host_addr.sin_family=AF_INET;
        host_addr.sin_port=htons(PORT);
        host_addr.sin_addr.s_addr=0;
        memset(&(host_addr.sin_zero),0,8);

        bind(socket_fd,(struct sockaddr *)&host_addr,sizeof(struct sockaddr));

        listen(socket_fd,3);

        while(1){
                size=sizeof(struct sockaddr_in);
                accepted_fd=accept(socket_fd,(struct sockaddr *)&client_addr,&size);

                send(accepted_fd,"Connected",10,0);
                printf("Client Info : IP %s, Port %d\n", inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));

                recv_length=recv(accepted_fd,&buffer,BUF_SIZE,0);
                while(recv_length>0){
                        printf("From Client : %s\n",buffer);
                        recv_length=recv(accepted_fd,&buffer,BUF_SIZE,0);
                }

                close(accepted_fd);
        }
        return 0;
}

 

여기서 포트번호는 12346을 사용한다고 하겠습니다.

 

socket_fd=socket(PF_INET,SOCK_STREAM,0);

socket의 첫번째 인자는 프로토콜 체계 PF(Protocol Family)를 지정합니다. PF_INET은 인터넷 IP프로토콜 체계입니다. 사용하는 프로토콜 체계에는 여러가지가 있습니다. IP외에도 1970년대에 개발된 공중 데이터 네트워크에 대한 표준 X.25 외에도 애플토크,XEROX 네트워크 등등 있는데 우리는 IP를 사용할 것이기 때문에 PF_INET만 사용할 것입니다.

 

두번째 인자는 소켓의 타입입니다. 가장 보편적으로 사용하는 타입은 Stream과 Datagram입니다. SOCK_STREAM은 연결형, SOCK_DGRAM은 비연결형이라고 생각하면 되겠습니다.

 

세번째 인자는 프로토콜로, 일반적으로 0을 넣어주면 시스템이 자동으로 설정해줍니다.

host_addr.sin_family=AF_INET;
host_addr.sin_port=htons(PORT);
host_addr.sin_addr.s_addr=0;
memset(&(host_addr.sin_zero),0,8);

bind(socket_fd,(struct sockaddr *)&host_addr,sizeof(struct sockaddr));

 

다음은 바인드할때 구조체를 넘겨야하는데요. 이 프로세스가 사용할 소켓 fd와 컴퓨터의 IP주소, 포트와 묶는 작업이라고 보면 됩니다.

 

우리는 TCP/IP 상에서의 통신이기 때문에 IPv4용 구조체인 sockaddr_in을 사용합니다.

sin_family에는 IP용 Address Family(AF_INET)을 지정합니다. 

sin_port는 이 프로세스가 사용할 포트번호를 지정합니다.

sin_addr.s_addr에는 주소가 들어가게 되는데요. 0은 현재 컴퓨터의 주소를 자동으로 채우라는 의미입니다. 그것이 아니라면 주소를 직접 지정해주어야합니다.

 

htons?

sin_port에서 htons는 무슨 함수일까요? 이 함수의 풀 네임은 host-to-network short로 16비트 정수를 호스트 바이트 순서에서 네트워크 바이트 순서로 변환하는 함수입니다.

AF_INET 소켓 주소 구조체에서 사용되는 포트 번호와 IP주소는 빅 엔디언(Big-Endian)이라는 네트워크 바이트 순서를 따릅니다. 이것은 보통 우리가 사용하는 x86의 리틀 엔디언과는 반대의 표기법이죠. 그래서 변환없이 그대로 사용하게 되면 바이트 순서가 달라지게 되어 제대로 동작하지 않습니다.

 

이제 bind를 호출하는데 두번째 인자를 보세요. (struct sockaddr*)로 형 변환하고 있습니다. host_addr이라는 구조체 변수는 sockaddr_in이라는 구조체입니다.

bind는 TCP/IP뿐만 아니라 X.25, 애플토크 등 여러 프로토콜이 존재하기 때문에 인자로 받아야할 구조체 형이 sockaddr_in뿐만이 아닙니다. 그래서 일반화된 구조체가 필요하게 되는데 그 구조체가 sockaddr입니다.

 

sockaddr_in은 sockaddr로 형변환할 수 있습니다. 왜냐하면 구조체의 크기가 같기 때문이죠. sockaddr 구조체는 2바이트의 Address Family와 14바이트의 주소를 사용합니다. 반면 sockaddr_in의 IPv4 전용 구조체는 sa_data의 주소를 포트번호, ip주소, 기타 추가 비트를 포함하고 있죠.  우리는 일반화된 sockaddr에 sa_data에 직접 포트번호와 주소를 읽고 쓰기가 상당히 불편합니다.

그래서 더 사용하기 편한 인터넷 전용 구조체를 사용합니다. 형변환에 문제가 없게 크기를 같게 만들어 호환성에 문제가 없습니다.

 

listen(socket_fd,3);

 

그 소켓으로 들어오는 연결을 기다립니다. 마지막인자는 백로그 큐의 최대크기입니다.

while(1){
	size=sizeof(struct sockaddr_in);
	accepted_fd=accept(socket_fd,(struct sockaddr *)&client_addr,&size);

	send(accepted_fd,"Connected",10,0);
	printf("Client Info : IP %s, Port %d\n", inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));

	recv_length=recv(accepted_fd,&buffer,BUF_SIZE,0);
	while(recv_length>0){
		printf("From Client : %s\n",buffer);
		recv_length=recv(accepted_fd,&buffer,BUF_SIZE,0);
	}

	close(accepted_fd);
}
        

 

 

 

accept를 통해서 이제 새롭게 연결된 클라이언트 전용 파일디스크립터를 얻어옵니다. 클라이언트에 대한 정보는 client_addr에 저장됩니다.

 

연결이 성공돼었다면 send를 통해서 "Connected"라는 문자열을 클라이언트 쪽으로 보냅니다.

그 후 클라이언트의 정보를 출력하지요. 두가지를 출력합니다. IP주소와 Port번호입니다.

 

inet_ntoa(struct in_addr *network_addr)

네트워크 주소를 숫자사이의 점을 찍는 IP주소로 network to acsii라는 뜻입니다. ip주소가 담긴 in_addr구조체는 32비트의 네트워크 주소를 갖고 있기 때문에 숫자사이에 점을 찍는 형태로 바꾸려면 이 함수를 사용합니다.

 

ntohs(Network-to-Host Short)

이것 역시 네트워크 바이트 순서가 빅 엔디안이고, 호스트의 바이트 순서가 리틀 엔디안일때 변환해야할때 사용합니다.

 

그 후에는 계속 recv를 통해 클라이언트에서 입력받은 메시지를 서버에서 그대로 출력해줍니다.

 

결과

서버

# gcc server.c
# ./a.out

 

클라이언트

# telnet 192.168.10.131 12348
Trying 192.168.10.131...
Connected to 192.168.10.131.
Escape character is '^]'.

Connected

 

서버

Client Info : IP 192.168.10.131, Port 43774

 

 

클라이언트

Hi
I'm Reakwon

 

서버

From Client :

From Client : Hi

From Client : I'm Reakwon

 

클라이언트에서 타이핑한 것이 서버에서 그대로 출력이 되는 것을 볼 수 있습니다.

 

이상으로 간단히 리눅스의 소켓과 그에 대한 예제를 보았습니다.

반응형
블로그 이미지

REAKWON

와나진짜

,

파이프와 더불어 더 많은 정보를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

파이프(Pipe)

파이프(Pipe)란 프로세스간 통신을 할때 사용하는 커뮤니케이션의 한 방법입니다. 가장 오래된 UNIX 시스템의 IPC로 모든 유닉스 시스템이 제공합니다. 하지만 두가지 정도의 한계점이 있습니다.

 

첫번째 한계점으로 파이프는 기본적으로 반이중 방식입니다. 물론 전이중 방식을 지원하는 시스템이 있긴 하나, 최대의 이식성을 위해서는 파이프는 반이중 방식이라는 생각을 해야합니다. 이것은 FIFO라는 명명된 파이프로 극복할 수 있습니다.

두번째 한계점으로는 부모, 자식 관계에서의 프로세스들만 사용할 수 있습니다. 부모프로세스가 파이프를 생성하고, 이후 자식 프로세스와 부모프로세스가 파이프를 이용하여 통신합니다.

 

이러한 한계점이 잇긴 하지만 여전히 쓸모있는 IPC기법입니다.

 

파이프는 unistd.h 헤더파일이 존재합니다.

 

#include <unistd.h>
int pipe(int fd[2]);

pipe함수가 성공적으로 호출되었다면 0, 실패했을 경우 -1을 반환합니다.

인자 fd는 2개의 원소가 있는 배열이라는 점을 주목합시다. 2개의 원소를 쓰는 이유가 있습니다. 아래의 그림을 보면서 이해합시다.

 

 

파이프는 커널영역에 생성되어 파이프를 생성한 프로세스는 파일 디스크립터만 갖고 있게 됩니다. 여기서 파일디스크립터 fd[1]은 쓰기용 파이프, fd[0]은 읽기용 파이프입니다. 그러니 우리가 만약 데이터를 fd[1]에 쓰게 되면 fd[0]으로 그 데이터를 읽을 수 있는 것입니다.

 

그렇다면 자식 프로세스를 하나 더 두어서 자식과 부모가 통신할 수 있게 하려면 어떻게 해야할까요? 우선 자식 프로세스를 fork하면 파일 디스크립터는 부모의 파일디스크립터를 자식이 그대로 사용할 수 있는 것을 활용합니다. (파일디스크립터가 그대로 자식프로세스에 복제됩니다.)

부모프로세스는 파이프에 데이터를 쓰는 프로세스, 자식 프로세스는 그 파이프에서 데이터를 읽는 프로세스로 설계합시다.

 

 

우선 부모 프로세스에서 파이프를 생성하면 파이프에 데이터를 쓸것이기 때문에 읽기 파이프는 닫습니다. fd[0]이죠? 그런 후 fd[1]에 데이터를 씁니다.

자식 프로세스는 쓰기 파이프는 쓰지 않으므로 fd[1]을 닫고, 읽기 파이프로 데이터를 읽습니다.

 

다음은 그런 기능을 하는 코드입니다.

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_BUF 1024
#define READ 0
#define WRITE 1
int main(){
        int fd[2];
        pid_t pid;
        char buf[MAX_BUF];

        if(pipe(fd) < 0){
                printf("pipe error\n");
                exit(1);
        }
        if((pid=fork())<0){
                printf("fork error\n");
                exit(1);
        }

        printf("\n");
        if(pid>0){ //parent process
                close(fd[READ]);
                strcpy(buf,"message from parent\n");
                write(fd[WRITE],buf,strlen(buf));
        }else{  //child process
                close(fd[WRITE]);
                read(fd[READ],buf,MAX_BUF);
                printf("child got message : %s\n",buf);
        }
        exit(0);
}

 

결과는 아래와 같습니다.

 

child got message : message from parent

 

자식 프로세스에서 부모 프로세스가 pipe에 쓴 데이터를 읽었습니다. 

또는 자식프로세스가 데이터를 쓰고, 부모프로세스가 데이터를 읽는 설계도 가능하겠죠.

 

 

그렇다면 부모 프로세스와 자식 프로세스가 읽기, 쓰기가 가능하게 구현하려면 어떻게 해야할까요? 파이프를 한개만 사용한다고 해봅시다.

 

그리고 이런 상황을 가정해보지요.

1. 먼저 부모프로세스가 파이프에 fd[1]로 데이터를 보냅니다. 

2. 그 이후 자식 프로세스가 부모 프로세스가 쓴 데이터를 fd[0]으로 읽습니다.

3. 자식 프로세스는 바로 fd[1]로 파이프에 응답값을 보냅니다.

4. 부모 프로세스는 fd[0]으로 자식 프로세스가 보낸 응답값을 읽습니다.

 

결론을 말씀드리면 항상 위의 상황은 발생하지 않습니다. 그 이유는 누가 먼저 파이프를 읽느냐에 따라서 결과가 달라지는데, 만일 부모프로세스가 파이프에 쓰고, 자식 프로세스가 그 데이터를 읽기도 전에 부모프로세스가 먼저 데이터를 읽는다면 파이프에 데이터는 없겠죠. 허나 자식 프로세스는 없는 데이터를 계속 읽기만 기다리고 있기 때문에 프로그램이 망하게 되는 겁니다.

 

이때는 파이프를 2개 사용해야합니다.

fdA와 fdB 2개 사용합니다. 부모프로세스는 자식에게 쓰기용으로 fdA[1], 자식프로세스로부터 읽기용으로 fdB[0]만 있으면 됩니다. 필요없는 fdA[0], fdB[1]은 닫아줍니다.

그리고 자식프로세스는 부모프로세스로부터 읽기용으로 fdA[0], 쓰기용으로 fdB[1]만 있으면 되지요. 역시 필요없는 fdA[1], fdB[0]은 닫아줍니다.

이제 이런 개념으로 코드를 구현합시다.

 

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_BUF 1024
#define READ 0
#define WRITE 1
int main(){
        int fdA[2],fdB[2];
        pid_t pid;
        char buf[MAX_BUF];
        int count=0;

        if(pipe(fdA) < 0){
                printf("pipe error\n");
                exit(1);
        }

        if(pipe(fdB) < 0){
                printf("pipe error\n");
                exit(1);
        }

        if((pid=fork())<0){
                printf("fork error\n");
                exit(1);
        }

        printf("\n");
        if(pid>0){ //parent process
                close(fdA[READ]);
                close(fdB[WRITE]);
                while(1){
                        sprintf(buf,"parent %d",count++);
                        write(fdA[WRITE],buf,MAX_BUF);
                        memset(buf,0,sizeof(buf));
                        read(fdB[READ],buf,MAX_BUF);
                        printf("parent got message : %s\n",buf);
                        sleep(1);
                }
        }else{  //child process
                close(fdA[WRITE]);
                close(fdB[READ]);
                count=100000;
                while(1){
                        sprintf(buf,"child %d",count++);
                        write(fdB[WRITE],buf,MAX_BUF);
                        memset(buf,0,sizeof(buf));
                        read(fdA[READ],buf,MAX_BUF);
                        printf("\tchild got message : %s\n",buf);
                        sleep(1);
                }
        }
        exit(0);
}

 

 

부모 프로세스는 0부터 1초마다 증가한 값을 파이프에 쓰고, 자식 프로세스로부터 파이프로 읽습니다. 자식 프로세스는 100000부터 증가한 값을 1초마다 쓰고, 읽습니다. 그 결과는 아래와 같습니다.

        child got message : parent 0
parent got message : child 100000
        child got message : parent 1
parent got message : child 100001
        child got message : parent 2
parent got message : child 100002
        child got message : parent 3
parent got message : child 100003
        child got message : parent 4
parent got message : child 100004
        child got message : parent 5
parent got message : child 100005

       

부모 자식 관계의 프로세스가 아닌 별개의 프로세스가 통신할때는 아까 위에서 말씀드린 것 처럼 FIFO를 사용해야합니다. 

 

파이프를 이용한 IPC구현, 이제 어렵지 않겠죠?

 

반응형
블로그 이미지

REAKWON

와나진짜

,

SSH(Secure Shell)

SSH란 원격에서 서버로 터미널에 접속할때 암호화를 통해 안전한 접속환경을 제공하여 telnet과 같은 안전하지 않은 원격 터미널 접속 프로그램을 보완하는 프로토콜 또는 프로그램입니다. SSH는 기본적으로 포트 22번을 사용합니다.

 

원격에서 telnet으로 서버에 접속할 경우 암호화 과정을 거치지 않으므로 스니핑을 한다면 계정과 비밀번호가 고스란히 노출됩니다. 하지만 ssh를 사용하여 접속한다면 암호화가 되었기 때문에 스니핑을 하여 패킷을 보더라도 의미를 파악할 수 없습니다. 또한 강력한 인증기능까지 지원합니다.

 

SSH의 주요 기능은

  • 보안 접속을 통한 rsh, rcp, rlogin, rexec, telnet, ftp 등을 제공합니다.
  • IP spoofing을 방지하기 위한 기능을 제공합니다.
  • X11 패킷 포워딩 및 일반적인 TCP/IP 패킷 포워딩을 제공합니다.

[출저 : 위키백과]

 

그렇다면 telnet접속과 ssh접속은 어떻게 다른지 눈으로 직접 살펴봅시다.

 

 

telnet으로 서버접속( 클라이언트 IP : 110.13.7.47 , 서버 IP : 110.13.7.20)

window 클라이언트에서 cmd에서 telnet을 통해 서버로 접속합니다.

엔터를 치는 순간 네트워크에서는 어떤 페킷이 오고 갔을까요? 아래는 와이어샤크로 본 페킷들입니다. 이 페킷을 보면 localhost login: 이라는 문자열을 볼 수 있습니다. 

서버(110.13.7.20)에서 클라이언트(110.13.7.47)로 보내는 군요. 그렇다면 클라이언트의 telnet 터미널 화면은 어떻게 됐을까요?

localhost login: 이라는 로그인 화면으로 들어왔습니다. 그렇다면 위의 페킷은 로그인하라는 디스플레이 메시지를 보냈다는 것을 짐작할 수 있겠군요.

 

이제 로그인을 시도해보지요. 아이디는 reakwon, 비밀번호는 reakwon입니다. 여기서 클라이언트(110.13.7.47)에서 서버(110.13.7.20)로 보내는 페킷만을 봅시다.

자, r이라는 문자를 보내는 군요. 이후에 75.6.355213의 페킷을 봅시다. r문자를 보낸 이후의 페킷입니다.

e라는 문자가 찍혔네요. 이렇게 reakwon이라는 문자를 서버에 보내고 서버는 그에 대한 응답으로 다시 reakwon이라는 문자를 각각 echo합니다. 이렇게 유저의 계정은 찾을 수 있습니다.

 

비밀번호 역시 다르지 않습니다. 이후의 페킷을 보면 알 수 있습니다. 다음은 계정의 비밀번호를 알아낼 수 있는 페킷들입니다. 하나씩 보도록 하지요.

페스워드의 시작을 알리는 페킷이 나옵니다. 

이후 아까처럼 reakwon의 문자들을 연속해서 서버에 보냅니다. 비밀번호를 입력할땐 서버로 부터 echo가 오지 않는군요.

이제 망했습니다. 해킹당했군요.

 

 

ssh로 서버접속( 클라이언트 IP : 110.13.7.47 , 서버 IP : 110.13.7.20)

다음은 ssh로 접속한 페킷들입니다. 대충보아도 서버와 클라이언트의 페킷이 암호화되었다고 하는군요. SSH버전은 2입니다.

페킷 하나를 보면 이렇습니다. 음, 암호화된 페킷을 보면 34e96..., 메시지 인증 코드는 14b4... 입니다. 

암호화된 페킷이라 잘 모르겠습니다. 암호화를 하여 데이터를 전송하고 수신하는 것만 알면 되겠습니다.

CentOS7에서 SSH로 서버 접속

CentOS7에서 ssh연결은 다음과 같은 과정을 거치는데요.

1. openssh-server 설치

2. 방화벽 열기

3. 가상머신을 돌릴 경우

 

1. openssh-server 설치

일단 ssh 서버가 설치되어 있어야합니다. 우선 설치되어 있나 확인을 해봅시다. 

 

[root@localhost etc]# rpm -qa | grep openssh-server
openssh-server-7.4p1-16.el7.x86_64

 

이미 설치가 되어있군요. 설치가 안된 분들은 설치하면 됩니다. 

다음의 명령으로 ssh 서버를 설치하세요.

 

yum install openssh-server

 

 

 

 

2-1. 방화벽 포트 열기

CentOS7에서는 기본적으로 방화벽(firewalld)가 설치되어 있습니다. 혹여나 설치가 되어있지 않은 분들은 yum install firewalld 명령으로 방화벽을 설치합시다.

 

ssh서버와 firewalld가 설치가 되었다면 방화벽에 ssh가 사용하는 포트를 열어줘야합니다. 그래서 /etc/ssh/sshd_config 파일을 열어 

(루트 사용자라면 vi /etc/ssh/sshd_config, 아니면 sudo vi /etc/ssh/sshd_config) 

#semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
#
#Port 22    <-- #해제
#AddressFamily any
#ListenAddress 0.0.0.0

 

에서 #Port 22의 주석을 해제합니다. 앞의 #을 지우게 되면 주석이 해제되는 겁니다. 이 후 sshd을 다시 시작해야되겠죠? 다음의 명령어로 sshd를 다시 시작합시다.

 

systemctl restart sshd.service

 

2-2. 방화벽 포트 열기

또는 다른 방법이 있는데요. 다음의 명령으로 방화벽에 명시해줍니다.

 

sudo firewall-cmd --permanent --add-service=ssh

 

이후 firewall의 변경사항을 적용하고 싶다면 

 

sudo firewall-cmd --reload

 

의 명령을 사용한 후 방화벽을 다시 시작해주어야합니다.

 

sudo systemctl restart firewalld

 

3. 혹시 가상머신을 사용해서 ssh를 쓰고 계신가요?

그럴 경우 설정-> 네트워크 -> 어댑터 -> 어댑터에 브릿지를 선택해주세요.

 

 

연결

자, 이제 putty라는 프로그램 또는 mobaXterm이라는 ssh 프로토콜이 가능한 프로그램을 사용해서 연결해봅시다. 일단 저의 ssh 서버의 주소는 ifconfig라는 명령어로 볼 수 있습니다. 

[root@localhost etc]# ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet 192.168.10.123  netmask 255.255.255.0  broadcast 192.168.10.255 

...

 

ssh의 서버주소는 192.168.10.123이군요. 이제 putty라는 프로그램으로 여기에 ssh로 접속해봅시다.

 

이제 open을 하게 되면 아래 처럼 로그인 화면이 나옵니다. 혹은 첫번째 실행이라면 뭐 yes, no를 묻는 대화창이 나오게 되는데 yes눌르시고 로그인하면 됩니다.

 

이제 원격에서도 ssh를 통해 서버에 접속 할 수 있습니다.

반응형
블로그 이미지

REAKWON

와나진짜

,

pwd (Print Working Directory)

현재 디렉토리를 알려주는 명령어입니다. 현재 유저가 어느 위치에 있는지 알아볼 수 있는 명령어입니다. 

 

아래의 예에서는 현재 작업디렉토리가 /home/reakwon이라는 디렉토리라는 것을 알 수 있습니다.

[reakwon@localhost ~]$ pwd

/home/reakwon

cd (Change Directory)

디렉토리를 이동하는 명령어입니다. 절대 경로나 상대 경로를 주어서 디렉토리를 이동할 수 있습니다. 

 

cd /root  = /root 디렉토리로 이동합니다.

cd ..  = 현재 디렉토리의 상위 디렉토리로 이동합니다.

cd ~ = 현재 사용자의 홈 디렉토리로 이동합니다.

 

이런 조합으로 이동이 가능합니다.

 

 

ls (List)

디렉토리 안의 파일과 디렉토리를 알 수 있는 명령어입니다. 여러가지 옵션이 존재하는데, 옵션은 여러가지를 혼합해서 사용할 수 있습니다. 옵션을 살펴보도록 하지요.

 

a : 모든 파일을 보여줍니다. 즉, 숨김파일까지 전부 보여주는 것이죠. 숨김파일이란 파일명 앞에 "."이 달린 파일명이고 ls명령어만으로 보여지지 않는 파일입니다.

 

l : (소문자 '엘') 파일의 자세한 내용을 보여줍니다. 

다음은 제 리눅스 pc의 tmp 디렉토리의 내용의 일부를 보여줍니다.

-rw-r--r--. 1 root    root    1148  5월 16 14:33 anaconda.log
drwx------. 2 reakwon reakwon   25  5월 16 14:50 firefox_reakwon
drwxr-xr-x. 2 root    root      18  5월 16 13:51 hsperfdata_root
-rw-r--r--. 1 root    root     420  5월 16 14:33 ifcfg.log
-rwx------. 1 root    root     836  5월 16 14:29 ks-script-o30BkB
-rw-r--r--. 1 root    root       0  5월 16 14:32 packaging.log
-rw-r--r--. 1 root    root       0  5월 16 14:32 program.log
-rw-r--r--. 1 root    root       0  5월 16 14:32 sensitive-info.log
drwx------. 2 reakwon reakwon   24  5월 16 14:34 ssh-TF6BwHbO3Rdo
drwx------. 2 reakwon reakwon   24  5월 16 14:41 ssh-UDg27UAVaZcs
drwx------. 2 reakwon reakwon   24  5월 16 23:13 ssh-bWUCqvi956kP
drwx------. 2 reakwon reakwon   24  5월 16 22:38 ssh-g8sqmExSvLtD
        1.    2.     3.         4.         5.          6.                  7.

 

1. 파일의 종류와 권한: 이 파일이 어떤 파일인지, 소유주, 소유주 그룹, 기타 다른 유저들이 이 파일을 사용할때의 권한을 보여줍니다. 

파일의 종류는 다음과 같습니다.

    a) - : 일반 파일

    b) d : 디렉토리

    c) b : block 장치 파일

    d) c : character 장치 파일

    e) l : 심볼릭 링크 파일

    f) p : 명명된 파이프

    g) s : 소켓 파일

 

권한은 다음과 같이 지정됩니다. 각 3개씩 권한이 나누어 지는데요.

rwx(파일 소유자의 권한)r-x(파일 소유 그룹의 권한)r-x(그외 사용자에 대한 권한)

r : read , w : write , x : execute

 

위의 파일 권한을 해석해본다면 파일 소유자는 읽기,쓰기, 실행 권한을 갖고 있네요. 파일 소유자가 있는 그룹은 이파일을 읽고, 실행만 할 수 있겠네요. 다른 사용자는 읽고, 실행만 할 수 있습니다.

 

2. 하드링크수를 보여줍니다. 

3. 파일의 소유주를 보여줍니다. 디렉토리를 만들거나 파일을 만든 계정입니다. 파일의 소유주는 chown명령어를 이용해 바꿀 수 있습니다.

4. 소유그룹을 보여줍니다. 파일 소유주의 그룹을 나타냅니다. 

5. 파일의 크기를 보여줍니다.

6. 최종 수정일, 시간을 보여줍니다.

7 마지막으로 파일명을 보여줍니다.

 

 

 

i : inode번호를 보여줍니다. 디렉토리에는 파일명과 해당 파일의 inode번호가 매핑되어 있는데, ls -l과 같이 파일의 자세한 정보를 볼 수 있는 것은 inode에 파일에 대한 메타데이터가 기록이 되기 때문입니다. 어떤 것들이 있는지는 아래와 같습니다.

  • 파일 모드 : 파일의 형식과 실행 권한
  • 링크 수 : 이 아이노드에 대한 디렉터리 참조 수
  • 소유자 계정 : 파일의 소유자
  • GID : 이 파일과 관계된 그룹 소유자
  • 파일 크기 : 파일의 바이트
  • 파일 주소 : 주소 정보
  • 마지막 접근(Access) : 마지막으로 파일에 접근한 시각
  • 마지막 수정(Modified) : 마지막으로 파일을 수정한 시각
  • 아이노드 수정(Changed) : 마지막으로 아이노드를 수정한 시각

: 하위 디렉토리의 내용까지 보여줍니다. 예를 들어 현재 디렉토리가 aaa이며 파일이 bbb,ccc 그리고 그 하위 디렉토리가 ccc이며 ccc의 디렉토리에 eee,fff 파일이 있다면 디렉토리 aaa의 파일을 전부 출력해주며 하위 디렉토리인 ccc의 내용까지 전부 출력해주는 옵션입니다.

: 디렉토리인지, 어떤 타입의 파일인지를 보여줍니다.

 

반응형
블로그 이미지

REAKWON

와나진짜

,

IP 클래스와 서브넷마스크


우리가 PC를 사용해 인터넷을 즐기고 게임을 하는 등 네트워크 통신에서는 항상 주소를 갖고 동작하고 있습니다. 그게 바로 IP 주소이지요. IP주소를 통해서 통신을 할 수 있는 겁니다.


우선 나의 아이피는 어떻게 알 수 있을까요?

윈도우에 cmd를 키고 ipconfig를 입력해보세요. 리눅스라면 ifconfig 명령어를 실행시켜보세요. 자신의 아이피주소가 나올겁니다.


이전에 컴퓨터의 수가 별로 없어서 IP주소를 막 뿌려댔으나 폭발적인 PC사용의 증가로 사태의 심각성을 깨달았는지 머리를 쓰게 된 것입니다.

그래서 나온게 서브넷마스크입니다.




본격적으로 IP클래스 대역과 서브넷마스크를 보기에 앞서 IP주소에 대해서 간단히 설명하고 넘어가도록 하겠습니다.


우리는 다음과 같은 IP주소를 갖고 있다고 칩시다.


192.168.10.10 -> 1100 0000. 1010 1000. 0000 1010. 0000 1010


십진수와 이진수로 나타냈습니다. 총 32비트, 4바이트라는 것을 알 수 있습니다. 여기서 1바이트가 바로 옥텟이라고 합니다. Oct가 숫자 8을 나타내는 접두사이거든요(온타곤, 옥토퍼스 등). 이것은 우리가 흔히 보는 IPv4의 주소 표기방식입니다. 


조금 후에 이야기를 하겠지만 이 IP주소가 C클래스 대역에 속한다면 네트워크 주소는 1100 0000. 1010 1000. 0000 0010입니다. 나머지 빨간 부분인 0000 1010은 호스트 주소랍니다. 그래서 192.168.10으로 시작하는 PC는 192.168.10.10과 같은 네트워크에 속하고 있다는 것을 의미합니다.


가장 첫번째 호스트 주소는 네트워크 자체를 지칭하며, 마지막 주소는 브로드캐스트용 주소로 쓰입니다. 예를 들어 위에서 192.168.10.0은 192.168.10의 네트워크를 가리키고, 192.168.10.255가 브로드캐스트용 주소이지요.


우리는 이제 IPv4를 토대로 IP 클래스 대역과 서브넷 마스크에 대해 알아보도록 하겠습니다.


A클래스

A클래스의 첫번째 옥텟의 비트는 0으로 고정됩니다.


0xxx xxxx. xxxx xxxx. xxxx xxxx. xxxx xxxx

그렇기 때문에 표현할 수 있는 범위는 0000 0000.0000 0000.0000 0000.0000 0000~0111 1110.1111 1111.1111 1111.1111 1111입니다.

그래서 0.0.0.0 ~ 127.255.255.255입니다.

이 IP클래스는 대규모 네트워크에 적합합니다.

네트워크 주소는 처음 8비트까지입니다. 나머지 24비트는 호스트 주소를 의미합니다.


B클래스

B클래스는 첫번째 옥텟의 두번째 비트가 고정됩니다. 10으로 고정이 됩니다.

10xx xxxx. xxxx xxxx. xxxx xxxx. xxxx xxxx

그래서 표현할 수 있는 범위는 1000 0000. 0000 0000. 0000 0000. 0000 0000~ 1011 1111. 1111 1111. 1111 1111까지입니다.

그래서 128.0.0.0 ~ 191.255.255.255입니다.

네트워크 주소는 처음 16비트이며 호스트 주소는 나머지 16비트입니다.




C클래스

C클래스는 첫번째 옥텟의 세번째 비트가 110으로 고정됩니다.

110x xxxx. xxxx xxxx. xxxx xxxx. xxxx xxxx

그래서 표현할 수 있는 범위는 1100 0000. 0000 0000. 0000 0000. 0000 0000 ~ 1101 1111. 1111 1111. 1111 1111. 1111 1111까지입니다.

십진수로 표현하면 192.0.0.0 ~ 223.255.255.255 입니다.

네트워크 주소는 처음 24비트이며 나머지 8비트는 호스트 비트입니다.


D클래스

D클래스는 첫번째 옥텟의 네번째 비트가 1110으로 고정됩니다.

1110 xxxx. xxxx xxxx. xxxx xxxx. xxxx xxxx

그래서 표현할 수 있는 범위는 1110 0000. 0000 0000. 0000 0000. 0000 0000 ~ 1110 1111. 1111 1111. 1111 1111. 1111 1111까지입니다.

십진수로 표현하면 224.0.0.0 ~ 239.255.255.255 입니다. 멀티캐스트용 대역으로 IP주소에 할당되지 않습니다.


E클래스

E클래스는 첫번째 옥텟의 네번째 비트가 1111으로 고정됩니다.

1111 xxxx. xxxx xxxx. xxxx xxxx. xxxx xxxx

그래서 표현할 수 있는 범위는 1111 0000. 0000 0000. 0000 0000. 0000 0000 ~ 1111 1111. 1111 1111. 1111 1111. 1111 1111까지입니다.

십진수로 표현하면 240.0.0.0 ~ 255.255.255.255 입니다. 예약된 주소 대역으로 IP주소에 할당되지 않습니다.


D와 E클래스는 특정 용도로 사용하기 때문에 실제 IP주소에 할당되지 않습니다.


클래스 등급이 낮아지면서 호스트 주소 부분이 점점 줄어들고 있는것을 알 수 있습니다.


이 와중에 특정 주소 대역은 사설 IP로 사용합니다. 아래에 나와있습니다.


A클래스 사설 IP주소 10.0.0.0 ~ 10.255.255.255

B클래스 사설 IP주소 172.16.0.0 ~ 172.31.255.255

C클래스 사설 IP주소 192.168.0.0 ~ 192.168.255.255 


또한 0.0.0.0, 255.255.255.255처럼 네트워크 시작 주소, 브로드캐스트용주소는 IP주소로 할당되지 않으면 127.0.0.1과 같은 loopback용 주소 또한 사용할 수 없습니다.


서브넷마스크


우리가 C클래스 대역을 사용해서 호스트를 255개를 수용할 수 있는 것도 너무 많이 남을때가 있습니다. 또는 B클래스 대역을 C클래스 대역으로 쓰고 싶을 때가 있습니다. 네트워크 주소를 조금 더 효율적으로 할당하고자 나온 것이 서브넷마스크입니다. 서브넷마스크로 만들어진 네트워크를 서브넷이라고 합니다.


이제 서브넷마스크를 어떻게 계산하며 네트워크 부분과 호스트부분이 어떻게 되는지 살펴봅시다.




예를 가지고 설명을 하는 것이 가장 좋겠네요.

128.255.11.11는 B클래스 주소입니다. 128.255까지가 네트워크 주소이며 나머지 2옥텟이 나머지 호스트 주소입니다.

128.255.11.11을 255.255.255.0이라는 서브넷 마스크를 씌우면 어떻게 될까요? 서브넷 마스크는 비트로 보는 것이 편합니다.


1000 0000.1111 1111.0000 1011.0000 1011 <- 128.255.11.11

1111 1111.1111 1111.1111 1111.0000 0000 <- 255.255.255.0


여기서 서브넷마스크 비트가 1인것은 전부 네트워크 주소가 됩니다. 반대로 0은 호스트 주소 범위가 되지요. 그래서 128.255.11이 네트워크 주소 대역이 되고 나머지 11이 호스트용 주소가 되겠네요.


서브넷마스크의 표기방식은 주소/서브넷마스크 주소 또는 주소/비트수로 표현할 수 있습니다. 128.255.11.11/255.255.255.0 또는 128.255.11.11/24로 표현가능하다는 것입니다.


조금 더 잘게 쪼개보겠습니다.

128.255.11.11을 255.255.255.224의 서브넷마스크를 적용하면 어떻게 될까요? 이 역시 비트로 풀어보도록 합시다.


1000 0000.1111 1111.0000 1011.0000 1011 <- 128.255.11.11

1111 1111.1111 1111.1111 1111.1110 0000 <- 255.255.255.224


하위 5비트 0 0000을 호스트용 주소로 적용시킬 수 있으니까 128.255.11.0 ~ 128.255.11.31까지가 같은 네트워크이고, 128.255.11.11이 바로 이 네트워크에 속하는 것을 알 수 있습니다.

전부 구해보면 다음과 같습니다.


128.255.11.0 ~ 128.255.11.31 

네트워크 주소 128.255.11.0, 브로드캐스트 주소 128.255.11.31

128.255.11.32 ~ 128.255.11.63

네트워크 주소 128.255.11.32, 브로드캐스트 주소 128.255.11.63

128.255.11.64 ~ 128.255.11.95

네트워크 주소 128.255.11.64, 브로드캐스트 주소 128.255.11.95

128.255.11.96 ~ 128.255.11.127

네트워크 주소 128.255.11.96, 브로드캐스트 주소 128.255.11.127

128.255.11.128 ~ 128.255.11.159

네트워크 주소 128.255.11.128, 브로드캐스트 주소 128.255.11.159

128.255.11.160 ~ 128.255.11.191

네트워크 주소 128.255.11.160, 브로드캐스트 주소 128.255.11.191

128.255.11.192 ~ 128.255.11.223

네트워크 주소 128.255.11.192, 브로드캐스트 주소 128.255.11.223

128.255.11.224 ~ 128.255.11.255

네트워크 주소 128.255.11.224, 브로드캐스트 주소 128.255.11.255




총 8개의 네트워크로 나누어졌음을 알 수 있습니다. (B클래스 대역이긴 하지만 C클래스처럼 0~255까지만 보았습니다.)


사실 위의 A,B,C클래스 대역은 서브넷마스크가 255.0.0.0, 255.255.0.0, 255.255.255.0의 서브넷마스크가 적용되었다는 사실을 눈치채셨나요? 이것을 default subnet mask라고 합니다.


반응형
블로그 이미지

REAKWON

와나진짜

,

TCP/IP

인터넷 프로그램들이 서로 통신을 하는데 있어서 여러 프로토콜이 있습니다. 인터넷 프로토콜에서 가장 많이 사용하는 대표적인 프로토콜은 여러분들도 많이 아시다시피 IP입니다. 여기서 중요한 것은 TCP/IP는 계층이 아니라 프로토콜이라는 사실이라는 사실을 주의해주세요.


TCP/IP는 OSI7 계층과는 조금은 다른 TCP/IP의 구조적인 계층 위에서 동작합니다.


지난 번에 OSI7 계층에 대해서 알아보았는데요. TCP/IP 계층은 OSI7계층과 비교하여 어떤 점이 다른지 살펴보는 시간을 가져보도록 하지요.






OSI7 계층과는 조금은 다른 모습을 볼 수 있습니다. 보세요.

우선 계층의 수 부터가 다릅니다. OSI는 7계층인데 반해 TCP/IP 계층은 4계층이 전부라는 것을 알 수 있습니다.


이제 조금 더 세세하게 살펴보도록 하지요.




1. 네트워크 인터페이스 계층 (Network Interface Layer)

이 계층은 Node-To-Node간의 신뢰성 있는 데이터 전송을 담당하는 계층입니다. OSI7 계층의 물리 계층과 데이터링크 계층의 역할을 바로 이 계층이 담당하는 것으로 볼 수 있네요.


따라서 MAC주소가 이 계층에서 사용됩니다. MAC주소는 OSI7 계층에서 데이터링크 계층의 주소였죠?? 


네트워크 인터페이스 계층이 바로 데이터링크 계층까지 담당하니까 MAC 어드레스가 사용되는 겁니다.


혹시 랜카드라고 들어보셨나요? 바로 이거말이에요.




정확한 명칭은 NIC라고 하여 Network Interface Card입니다. 바로 이 랜카드가 있어야만 네트워크 통신을 할 수 있는데, 이름에서도 알 수 있듯이 네트워크 인터페이스 계층에서 동작하는 장비입니다.


주요 프로토콜을 무엇이 있을까요?

LAN상에서는 Ethernet, TokenRing, FDDI 등이 있으며 WAN 상에서는 X.25, Frame Relay, PPP 등이 있습니다.


2. 인터넷 계층 (Internet Layer)

OSI7계층의 네트워크 계층을 담당하는 계층입니다. OSI7 계층처럼 호스트간의 라우팅을 담당하지요. 


인터넷 계층에서 동작하는 프로토콜에는 무엇이 있을까요? 대표적인 몇가지 프로토콜을 살짝 알아보도록 합시다.


IP(Internet Protocol) : 비신뢰성, 비연결지향 데이터그램 프로토콜입니다. 

ARP(Address Resolution Protocol) : 주소변환 프로토콜입니다. IP주소를 MAC주소로 변환하는 프로토콜이지요.

RARP(Reverse ARP) : 반대로 MAC주소로 IP주소를 찾는 프로토콜입니다.

ICMP(Internet Control Message Protocol) : 상태 진단 메시지 프로토콜인데요. 이 프로토콜을 이용하는 대표적인 프로그램이 ping입니다.

IGMP(Internet Group Message Protocol) : 멀티캐스트용 프로토콜입니다.




3. 전송 계층 (Transport Layer)

OSI7 계층의 전송계층과 같습니다. 프로세스간의 신뢰성 있는 데이터 전송을 담당하는 계층입니다.


process-to-process 전송을 담당하기 위해서는 논리적 주소가 필요한데요. process가 사용하는 포트 번호를 그 논리적 주소로 사용합니다.


전송 계층에서 프로토콜은 무엇이 있을까요?


TCP (Transmission Control Protocol) : 신뢰성있는 연결지향형 프로토콜입니다. 신뢰성있다는 말은 그 페킷에 대한 오류처리나 재전송따위로 에러를 복구하는 것을 말합니다. 그때문에 TCP의 헤더에 붙는 정보가 많습니다.

UDP (User Datagram Protocol) : 비신뢰성 비연결형 프로토콜입니다. 페킷을 잃거나 오류가 있어도 대처하지 않는 것을 말합니다. 따라서 UDP헤더는 간단한 구조를 갖고 있습니다.



4. 응용 계층 (Application Layer)

사용자와 가장 가까운 계층입니다. OSI7계층의 5계층부터 7계층까지의 기능을 담당하고 있지요.

서버나 클라이언트 응용 프로그램이 이 계층에서 동작합니다. 우리가 알고 있는 브라우저나 텔넷같은 서비스가 이 계층에 동작하며, 동작하기 위해서는 전송계층의 주소, 즉 포트번호를 사용합니다.


이를테면 http는 포트번호 80번을 사용하지요.


역시 프로토콜은 무엇이 있나 살펴볼까요?


HTTP (Hyper-Text Transfer Protocol) : TCP기반의 프로토콜로 포트번호 80번을 사용합니다.

Telnet : TCP 포트번호 23번을 사용합니다. 원격 터미널을 접속할때 이 포로토콜을 사용합니다.

SSH (Secure Shell) : 텔넷과 같은 서비스는 보안에 취약합니다. 비밀번호가 암호화되지 않아 그대로 노출이 되기 때문이지요. 이것을 보완한것이 SSH입니다. 포트번호 22번을 사용합니다.

FTP(File Transfer Protocol) : 파일 전송 프로토콜입니다. 파일을 받거나 올릴때 FTP를 사용하지요. FTP는 파일을 올리거나 내려받을때 신뢰성을 중요시하기 때문에 TCP에서 동작하구요. 2개의 포트를 사용합니다. 

TCP 포트 20번은 데이터 전송을 위한 용도, TCP 포트 21번은 제어용으로 사용합니다.

SMTP (Simple Mail Transfer Protocol) : 메일 전송 프로토콜입니다. TCP 상에서 동작하며 포트는 25번을 사용합니다.

POP3 (Post Office Protocol Version3) : 메일 수신용 프로토콜입니다. 아웃룩같은 프로그램이 POP3라는 프로토콜을 사용하여 동작합니다. TCP 포트 110번을 사용합니다.

DNS (Domain Name System) : 도메인명에 대한 호스트 정보를 제공해줍니다. 기본적으로 UDP상에서 동작합니다. 기본적으로 실패하면 다시 한번 요청하면 되며 그렇게 중요한 정보가 아니기 때문이죠. 하지만 신뢰성을 요할 경우에는 TCP상에서도 동작합니다. 데이터의 길이가 길 경우같은 때 TCP 기반으로 동작할 수 있습니다.

UDP, TCP 포트 53번을 사용합니다.




이와 같이 포트번호가 특정 프로토콜이 사용해서 우리가 쓸 수 없는 포트들이 있습니다. 이런 포트들을 well-known port라고 합니다.


프로토콜 헤더 정보를 잘 읽고 분석할 수 있다면 네트워크를 더 잘 이해할 수 있을 겁니다.


따라서 다음 시간에는 헤더를 보고 무슨 정보가 있는지 살펴보는 기회를 갖도록 하겠습니다.

반응형
블로그 이미지

REAKWON

와나진짜

,

네크워크의 기본 OSI7 계층


네트워크에서 아주 기본적인 지식은 OSI7 계층입니다. OSI7계층은 국제 표준기구인 ISO(International Organization for Standardization)으로부터 탄생합니다.


처음 네트워크 장치는 중구난방이었습니다. 때문에 회사의 장비마다 호환이 되지 않으며 복잡했었죠. 이에따라 네트워크를 7계층으로 분리하면서 표준을 만들게 되었습니다. 그것이 바로 OSI 7 계층입니다.



OSI 7 계층 구조





이렇게 생겨먹었습니다. 딱 7개로 나뉘어져 있지요?


그림을 보면 알겠지만 응용계층에서 내려온 데이터부터 시작해서 계속 헤더가 붙는 것을 알 수 있습니다. 이 헤더에는 그 계층에 대한 정보가 기록되어있지요.


우리가 이메일을 보낸다고 가정할때 처음 응용계층에서 헤더를 붙여 하위 계층으로 넘겨줍니다. 표현계층은 응용계층에서 내려온 헤더와 이메일 데이터를 하나의 데이터로 간주하게 됩니다. 그래서 다시 자신의 헤더를 붙이게 되지요. 이런 과정은 Encapsulation이라고 합니다.

이런식으로 물리계층까지 내려오게 되면 그때부터 0과 1의 이진 비트가 전송되게 되는 것입니다.


받은 수신자는 거꾸로 물리계층부터 시작해 헤더의 정보를 확인하고 떼어냅니다. 그리고 난 후 상위 계층으로 데이터를 전달하는 것이죠. 이렇게 헤더를 떼어내는 과정은 Decapsulation이라고 합니다.




지금부터 응용계층부터 물리계층까지 간략하게 설명하도록 하지요.


물리계층(Physical Layer)


7계층 중 최하위 계층입니다. 주로 전기적, 기계적, 기능적인 특성을 이용해 데이터를 전송하게 됩니다. 데이터는 0과 1의 비트열, 즉 On, Off의 전기적 신호 상태로 이루어져있지요.


이 계층은 단지 데이터를 전달하기만 합니다. 어떤 에러가 있는지 등 그런 기능에는 전혀 관여하지 않습니다.


데이터링크 계층(Data-Link Layer)


물리 계층에서 송수신되는 정보의 오류와 흐름을 관리하여 안전한 정보의 전달을 수행할 수 있도록 도와주는 역할을 합니다.

데이터 링크 계층의 데이터 전송은 Point-To-Point 간 입니다. 

안전한 정보의 전달이라는 것은 오류나 재전송하는 기능을 갖고 있다는 이야기죠. 또한 우리가 언젠가 한번 들었을 MAC주소를 갖고 있습니다. 그래서 통신을 할 수 있지요.


이 계층에서 부르는 데이터의 단위는 프레임(Frame)이라고 합니다.


네트워크 계층(Network Layer)


네트워크 계층은 네트워크에서 아주 중요합니다.

중요한 기능 중 한가지는 바로 라우팅이라고 하는데요. 목적지까지 가장 안전하고 빠르게 데이터를 보내는 기능을 말합니다. 따라서 최적의 경로를 설정해야하지요.

이런 라우팅 기능을 맡고 있는 계층이 네트워크 계층입니다.


또한 어느 컴퓨터에게 데이터를 전송할지 주소를 갖고 있어서 통신을 합니다. 우리가 자주 듣는 IP 주소가 바로 네트워크 계층 헤더에 속해있습니다.


네트워크 계층에서 부르는 데이터 단위는 패킷(Packet)이라고 합니다.


전송 계층(Transport Layer)

전송 계층 역시 네트워크에서 중요한 계층입니다. 전송 계층은 양 끝단의 사용자들이 신뢰성있는 데이터를 주고 받게 해주는 역할을 합니다.

송신자와 수신자 간의 신뢰성있고 효율적인 데이터를 전송하기 위하여 오류검출 및 복구, 흐름제어와 중복검사 등을 수행합니다.


중요한 것은 데이터 전송을 위해서 Port 번호가 사용이 됩니다. 대표적인 프로토콜로는 TCP와 UDP가 있습니다. 이 계층에서 사용하는 데이터 단위는 세그먼트(Segment)라고 합니다.




세션 계층(Session Layer)


세션 계층은 응용 프로세스가 통신을 관리하기 위한 방법을 정의합니다. 

이 계층은 세션을 만들고 없애는 역할을 하고 있지요.


표현 계층(Presentation Layer)

데이터를 어떻게 표현할 지 정하는 역할을 하는 계층으로 일종의 확장자라고 이야기하면 편하겠네요.

표현 계층은 세가지의 기능을 갖고 있습니다.


1. 송신자에서 온 데이터를 해석하기 위한 응용계층 데이터 부호화, 변화

2. 수신자에서 데이터의 압축을 풀수 있는 방식으로 된 데이터 압축

3. 데이터의 암호화와 복호화


MIME 인코딩이나 암호화 등의 동작이 표현계층에서 이루어집니다. EBCDIC로 인코딩된 파일을 ASCII 로 인코딩된 파일로 바꿔주는 것이 한가지 예이지요.


응용 계층(Application Layer)


사용자와 가장 가까운 계층이 바로 응용 계층입니다. 우리가 사용하는 응용 서비스나 프로세스가 바로 응용계층에서 동작합니다.


이상 OSI 7 계층에 대해서 알아보았습니다.

반응형
블로그 이미지

REAKWON

와나진짜

,