카테고리 없음

[펌] Socket Layer

achivenKakao 2005. 4. 13. 21:56
Socket Layer
Posted on 2002/5/30
Topic: TCP/IP
article_socket_layer위키 홈으로

Socket

윤 상배

dreamyun@yahoo.co.kr


차례
1절. Socket 에 대한 기본지식
1.1절. Socket Layer
1.2절. 왜 Layer 구조를 가지는가
1.3절. Socket
1.4절. socket API
1.4.1절. socket(2) 함수
1.4.2절. bind(2) 함수
1.4.3절. connect(2) 함수
1.4.4절. listen(2) 함수
1.4.5절. accept(2) 함수
1.5절. 소켓 생성 순서
1.5.1절. 서버측 socket 생성 순서
1.5.2절. 클라이언트 측 socket 생성순서
2절. 결론

1절. Socket 에 대한 기본지식

1.1절. Socket Layer

Socket 은 유닉스의 파일 기술자를 통해서 다른 프로그램간의 정보교환을 가능하도록 해주는 방법으로, 같은 시스템에 있는 프로그램들간의 정보교환을 위한목적, 혹은 다른 시스템(네트웍 상으로 멀리떨어져있는) 들간의 정보교환을 위한 목적으로 사용된다.

그런데 왜 Layer 라고 부르는가 그 이유는 TCP/IP 4계층의 응용계층(applicaton layer)과 전송계층(transmission layer) 중간에 존재하기 때문이다. 아래의 그림을 보라

    +----------+        HTTP Protocol           +----------+    | Browser  | <- - - - - - - - - - - - - ->  | Server   | Application Layer    +----------+                                +----------+       ↓↑                                         ↓↑    ------------------- <Socket Layer> ---------------------------------------       ↓↑                                         ↓↑    +----------+         TCP protocol           +----------+    | TCP      | <- - - - - - - - - - - - - ->  | TCP      | Transport Layer    +----------+                                +----------+       ↓↑                                         ↓↑    +----------+         IP protocol            +----------+    | IP       | <- - - - - - - - - - - - - ->  | IP       | Internet Layer     +----------+                                +----------+       ↓↑                                         ↓↑    +----------+       Ethernet Protocol        +----------+    | Etnernet | <- - - - - - - - - - - - - ->  | Etnernet | Physical Layer     +----------+                                +----------+       ↓↑                                         ↓↑    =========================================================                          TCP/IP ??                            INTERNET			
위의 그림은 TCP/IP 개요에서 이미 본적이 있는 그림일 것이다. 그때의 그림과 달라진 점이 있다면, 응용계층과 전송계층에 Socket Layer 가 존재한다는 것이다. 이 Socket Layer 가 응용계층과 전송계층 사이에 존재하게 됨으로 우리 프로그래머들은 복잡하게 TCP 를 직접 제어할 필요없이, Socket Layer 에서 제공하는 다양한 함수(Socket API)를 이용해서 간단하게 인터넷 네트웍 프로그래밍 작업을 하게 되는것이다.

Socket Layer 은 응용계층에서 받은 메시지를 하부 Socket API 를 이용해서 전송계층으로 보낸다. 전송계층에는 2가지 대표적인 프로토콜 이 있는데 바로 TCP 와 UDP 이다. 그럼으로 우리 프로그래머들은 TCP 프로토콜을 사용할것인지 UDP 프로토콜을 사용할것인지만 결정해주면된다.


1.2절. 왜 Layer 구조를 가지는가

일상 생활에서 소켓레이어와 비슷한게, 전화기라고 볼수 있을것이다. 우리는 상대편에서 전화를 걸기 위해서 상대편전화의 지리적 위치가 어디인지, 어떤 전화국에서 관리하는지, 언어를 신호로 변환 시키기 위해서 어떠한 작업을 해야하는지, 어떻게 보내야 하는지 전혀 알필요가 없다. 그냥 수화기 들고 전화 번호만 누르면 그걸로 끝이다. 즉 전화기 라는게 있음으로 그 내부에서 일어나는 여러가지 복잡한 통신 프로세스를 모르고도 상대편과 전화통화를 할수 있게 된다.

Socket Layer 이 존재함으로써, 우리는 TCP/UDP 헤더를 어떻게 만들어야 하는지, 구조가 어떻게 되는지, 어떻게 커널에 전달해야 하는지 신경쓸필요 없이 네트웍 프로그램을 만들수 있게 된다.


1.3절. Socket

"Socket 이라뇨 우리는 위에서 Socket Layer를 이미 다루었는데요 ?" 라고 의문을 가질수도 있을것이다. Socket Layer 과 Socket 는 엄연히 다르다. Socket Layer 는 계층을 나타내는 것이다. 즉 Socket 를 다루기 위한 계층이다. 이는 TCP가 전송계층이 아닌것과 마찬가지이다. 우리는 Socket Layer 에서 제공하는 다양한 API를 통해서 Socket 를 제어하게 된다.

그럼 Socket 이란 무엇인가. 소켓이란 유닉스 파일 지시자 를 이용하여 다른 프로그램과 정보교환을 하는 방법(혹은 도구) 이다. 일반적으로 유닉스 상에서 정보교환은 파일지시자를 통한다는걸 알고 있을것이다. 마찬가지로 Socket 를 이용한 지역 혹은 네트웍으로 연결된 프로그램 간의 정보교환 역시 파일지시자를 통해서 이루어진다.

다중연결서버 만들기(1) 의 zipcode_multi.c 를 이용해서 소켓이 어떻게 작동하는지 알아보도록 하겠다. 먼저의 위의 프로그램을 컴파일 시키고 작동을 시켜보자. 작동을 시켰다면 ps 로 zipcode_multi 프로그램의 pid 를 확인해보고 /proc/pid/fd 디렉토리로 이동해서 어떠한 파일 지시자를 가지고 있는지 확인해보도록 하자.

[yundream@localhost test]# ./zipcode_multi 4444...[yundream@localhost test]# ps -ax | grep zipcode  2473 ttyp1    S      0:00 ./zipcode_multi 4444			
pid가 2473 이므로 이 프로그램의 /proc/2473/fd 로 이동해서 ls해보면 프로그램에서 사용하고있는 파일지시자들에 대해서 알수 있다.
[yundream@localhost test]# ls -al /proc/2473/fd합계 0dr-x------    2 root     root            0  5월 28 16:07 .dr-xr-xr-x    3 root     root            0  5월 28 16:07 ..lrwx------    1 root     root           64  5월 28 16:14 0 -> /dev/ttyp1lrwx------    1 root     root           64  5월 28 16:14 1 -> /dev/ttyp1lrwx------    1 root     root           64  5월 28 16:14 2 -> /dev/ttyp1lr-x------    1 root     root           64  5월 28 16:14 3 -> /home/mycvs/test/zipcode.txtlrwx------    1 root     root           64  5월 28 16:14 4 -> socket:[171434]			
0, 1, 2 는 각각 표준입력, 표준출력, 표준에러를 가리키는 파일지시자 라는것은 이미 알고 있을것이다. 3 은 프로그램이 연 파일을 가리킨다. 마지막 4가 바로 socket 통신을 위해 만들어진 파일 지시자이다. 다른 것들이 터미널이나 파일을 가리키는것과는 달리 socket 를 가리 키고 있음을 알수 있다.

여기에 새로운 클라이언트가 접근을하면 (telnet 이나 전용클라이언트 를 이용해서) 다음과 같은 파일 지시자가 하나 추가 될것이다.

lrwx------    1 root     root           64  5월 28 16:14 5 -> socket:[171435]			


1.4절. socket API

이번에는 socket 레이어에서 제공하는 소켓 관련 함수들을 설명하도록 하겠다.


1.4.1절. socket(2) 함수

이러한 소켓 은 socket(2) 함수를 이용해서 만들어진다. 최초 socket 함수를 이용해서 소켓을 생성하면 커널은 통신을 위한 종점(end point,즉 통신연결상황을 체크하는)을 생성하고, 여기에 대한 파일 지시자를 되돌려준다. 프로그램은 socket 함수를 이용해서 생성한 파일 지시자에 새로운 연결이 들어오는 지를 확인하게 된다.

위에 있는 TCP/IP 4계층을 보면 Socket Layer 아래에는 최소한 2개 이상의 사용가능한 데이타 그램의 타입이 있음을 알수 있다. 이러한 데이타 그램의 타입에는 TCP, UDP, RAW 등이 있다. TCP 소켓, UDP 소켓, RAW 소켓이라고 부르기도 한다. 또한 다양한 소켓 주소패밀리(군)를 제공한다.

표 1. 소켓주소 패밀리

UNIX유닉스 도메인 소켓, IPC 용으로 많이 사용한다.
INETTCP/IP 프로토콜을 이용한 인터넷주소 패밀리, 보통의 네트웍프로그래밍시 주로 사용
IPX노벨의 IPX 프로토콜, 게임을 좋아한다면 많이 들어봤음직한
AX25아마추어 라디오 X.25
X25X.25 프로토콜

그러므로 socket 함수는 위의 소켓 주소 패밀리와 소켓 타입 지정이 가능해야 한다.

int socket(int domain, int type, int protocol);				
첫번째 아규먼트가 소켓주소 패밀리 지정을 위해서 사용되며, 두번째 아규먼트가 소켓 타입지정을 위해서 사용된다. 소켓주소 패밀리는 주로 INET(AF_INET), UNIX(AF_UNIX) 가 사용되며, 소켓타입은 TCP(SOCK_STREAM), UDP(SOCK_DGRAM), RAW(SOCK_RAW) 가 사용된다.

즉 인터넷 프로토콜을 이용하는 TCP 소켓을 만들기 원한다면 socket(AF_INET, SOCK_STREAM, 0) 과 같이 사용하면 된다.

socket 함수가 성공적으로 수행되면, 사용가능한 소켓을 가르키는 파일 지시자를 되돌려주며, 이 파일지시자는 endpoint(연결 확인 통로) 로써 사용된다.


1.4.2절. bind(2) 함수

socket 함수를 이용해서 만들어진 소켓에 이름을 부여한다.

라고 번역된 man 페이지혹은 관련된 번역서에서 설명을 하고 있지만, 소켓에 특성을 부여(소켓과 특성을 묶는다(bind))한다 라는게 좀더 적당한 설명이 아닐까 싶다.

int bind(int  sockfd, struct sockaddr *my_addr, socklen_t addrlen);				
인자로 주어진 sockfd 에대해서 sockaddr 을 이용해서 특성을 묶어준다. bind 함수를 통해서 우리는 sockfd 가 사용할 포트번호(port), 그리고 연결을 받아들일 IP 주소 특성등을 묶어줄수 있다. IP 주소는 IPv4, IPv6 등이 사용될수 있을것이다.

bind 함수는 보통 서버에서 사용된다. 그 이유는 대부분의 서비스(HTTP, FTP..)들이 지정된 포트번호를 통해서 서비스 되기 때문이다. 반면 클라이언트의 경우 커널에서 할당한 임의의 포트번호를 이용해서 서버와 연결하기 때문에 bind 를 사용할 필요가 없다.


1.4.3절. connect(2) 함수

int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);				
이것은 클라이언트측 에서 사용되며, struct sockaddr 구조체에 세팅된 내용대로 서버측에 연결한다. sockaddr 구조체에는 연결될 서버에 대한 정보들, 즉 주소 패밀리 IP 번호와 PORT 번호 등이 들어가 있으며, connect 함수는 sockaddr 정보를 이용해서 서버측에 연결을 하며 서버와의 통신을 위한 endpoint 와 sockfd 를 연결시킨다. sockfd 는 socket 함수를 이용해서 만들어진 소켓 지정 번호이다.


1.4.4절. listen(2) 함수

int listen(int sockfd, int backlog);				
서버측에서 사용되며 socket 함수를 이용해서 만들어진 sockfd 에 대해서, 들어 오는 연결을 기다린다. backlog 는 아직 완전히 연결되지 않은 연결들이 대기할 queue 의 길이를 명시하기 위해서 사용된다.


1.4.5절. accept(2) 함수

int accept(int s,  struct  sockaddr  *addr,  socklen_t *addrlen); 				
listen 을 통해서 만들어진 미연결의 대기열에서 가장 앞에 있는 연결의 내용을 가져와서 새로운 연결 소켓을 만들어준다. 새로만들어진 연결소켓은 파일 지시자를 할당하여서 리턴해주게 되며, 우리는 리턴된 파일 지시자를 이용해서 새로만들어진 소켓과 통신을 할수 있게 된다.


1.5절. 소켓 생성 순서

1.5.1절. 서버측 socket 생성 순서

다음은 서버측의 소켓 생성 순서를 나열한 것이다.

  1. 서버측의 소켓 생성순서는 최초 socket 함수를 이용해서 endpoint 소켓, 즉 클라이언트의 연결을 듣기 위한 소켓을 생성하게 된다. 이 소켓은 서버가 종료될때까지 남아있게 된다.

  2. bind 함수를 호출하여 소켓특성을 묶어준다. 이 함수를 이용하여 port 번호를 지정해주며, 받아들일 IP주소에 대한 설정을 한다.

  3. listen 함수를 이용하여 듣기 소켓(socket 함수를 통해서 만들어진) 에 연결이 있는지 기다린다. 만약 연결이 있다면, 연결 대기열(queue)에 쌓아놓는다.

  4. accept 함수를 이용하여 연결 대기열에 대기중인 연결이 있다면 해당 연결에 대하여 새로운 소켓을 만들고 만들어진 소켓에 대한 파일 지시자를 되돌려준다. 이 소켓은 읽기/쓰기로 만들어진다. 만약 연결 대기열에 대기중인 연결이 없다면 (기본적으로) 해당 영역에서 봉쇄(block)된다.

  5. read, write 등의 함수를 이용해서 통신을 한다.


1.5.2절. 클라이언트 측 socket 생성순서

다음은 클라이언트측의 소켓 생성 순서를 나열한 것이다. 서버측에 비하여서 훨신 간단하게 이루어짐을 알수 있다.

  1. 최초 socket 를 이용하여 endpoint 소켓을 생성한다. 클라이언트 이므로 이것은 듣기 소켓이 아니고, 연결 소켓이 될것이다. (이름만 다를뿐 사실 듣기 소켓과 연결 소켓의 구분은 없다)

  2. connect 를 이용하여 서버에 연결한다.

  3. read, write 등의 함수를 이용해서 서버와 통신한다.


2절. 결론

이상 Socket Layer 의 개념과 Socket Layer 에서 제공하는 Socket API 에 대한 간단히 알아 보았다. 여기에 있는 API 들은 가장 기본적인(통신을 위해서 필요한) 함수들이다. 나머지 좀더 세밀한 함수들에 대해서는 Unix NetWork Programming 등의 서적을 참고하기 바란다.

여기에 있는 소켓 API 들의 사용예는 이 사이트에서 충분히 찾아볼수 있을것이다.