2017. 1. 18. 16:26 IT

소켓(Socket) 설명. 이해.

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

소켓(Socket)의 이해


2.1.1 소켓의 정의


▶ 소켓(socket)은 1982년 BSD(Berkeley Software Distribution) UNIX 4.1에서 처음 소개되으며 현재 널리 사용되는 것은 1986년의 BSD UNIX 4.3에서 개정된 것이다.


▶ 소켓은 소프트웨어로 작성된 통신 접속점이라고 할 수 있는데 네트웍 응용 프로그램은 소켓을 통하여 통신망으로 데이터를 송수신하게 된다.


▶ 그림 2-1에 세 개의 응용 프로그램이 각각 소켓을 통하여 TCP/IP를 공유하고 있는 것을 나타냈다.


▶ 소켓은 응용 프로그램에서 TCP/IP를 이용하는 창구 역할을 하며 응용 프로그램과 소켓 사이의 인터페이스를 소켓 인터페이스라고 한다.


▶ 한 컴퓨터내에는 보통 한 세트의 TCP/IP가 수행되고 있으며, 네트웍 드라이버는 LAN 카드와 같은 네트웍 접속 장치(NIU: Network Interface Unit)를 구동하는 소프트웨어를 말한다.




2.1.2 소켓번호


▶UNIX에서 파일을 새로 열면(open) int 타입의 정수를 리턴하는데 이와같이 open문이 리턴한 정수를 파일기술자(file descriptor)라고 하며 프로그램에서 open된 파일을 액세스할 때 이 파일기술자를 사용하게 된다.


▶ 파일기술자는 기술자 테이블(descriptor table)의 index 번호인데(그림 2-2 참조), 기술자 테이블이란 현재 open되어 있는 파일의 각종 정보를 포함하고 있는 구조체를 가리키는 포인터들로 구성된 테이블이다.


▶ 예를들어 한 응용 프로그램내에서 2개의 파일을 open하면 파일기술자는 3과 4가 배정된다


 




▶ 프로그램에서 소켓을 개설하면 파일기술자와 똑같은 기능을 하는 소켓기술자(socket descriptor)가 리턴된다.


▶ 응용 프로그램에서 이 소켓을 통하여 목적지 호스트와 연결을 요구하거나 패킷을 송수신할 때 해당 소켓기술자를 사용하게 된다(이 책에서는 편의상 소켓기술자를 소켓번호라고 부르겠다).


▶ UNIX에서는 파일기술자와 소켓기술자가 같은 기술자 테이블의 index가 된다. 즉, 파일과 소켓이 기술자 테이블을 공유한다.


▶ 한 프로세스에서 파일 open시 리턴되는 파일기술자와 소켓 개설시 리턴되는 소켓기술자의 값은 서로 중복된 것이 없게 된다.


▶ 그림 2-2에는 두 개의 파일과 한 개의 소켓을 개설하였을 때의 기술자 테이블과 기술자 테이블이 가리키는 파일 또는 소켓 데이터 구조체를 나타내고 있다.


▶ 그림 2-3에 응용 프로그램과 소켓 그리고 TCP/IP의 관계를 구체적으로 나타냈다.


▶ 네 개의 응용 프로그램이 소켓번호로 각각 4, 3, 3, 3을 사용하고 있는 것을 나타냈다(응용 프로그램 1은 파일을 하나 먼저 열고 있으므로 소켓번호가 4가 된 것이다).


▶ 한편 소켓번호는 응용 프로그램내에서 순서대로 배정되며 그 프로그램내에서만 유일하게 구분되면 되는 것이므로 서로 다른 응용 프로그램에서 같은 소켓번호를 사용하는 것은 문제가 되지 않는다.


▶ 포트번호는 TCP/IP가 지원하는 상위 계층의 프로세스를 구분하기 위한 번호이므로 하나의 컴퓨터내에 있는 응용 프로세스들은 반드시 서로 다른 포트번호를 사용하여야 한다.


▶ 그림 2-3에서는 네 개의 응용 프로그램이 3000번부터 3003번의 포트번호를 사용하는 것을 가정하였다.


▶ 그림 2-3에서 연결형 서비스는 TCP가 그리고 비연결형 서비스는 UDP가 각각 처리하는 것을 보였다.



2.1.3 소켓의 이용


▶ 소켓을 이용한 네트웍 응용 프로그램에서 상대방과 IP 패킷을 주고받기 위하여는 다음의 다섯 가지 정보가 정해져야 한다.

① 통신에 사용할 프로토콜(TCP 또는 UDP)

② 자신의 IP 주소

③ 자신의 포트번호

④ 상대방의 IP 주소

⑤ 상대방의 포트번호


▶ 통신에 사용할 프로토콜은 연결형 또는 비연결형을 말하는데 인터넷 프로그램에서는 연결형 서비스를 TCP 또는 스트림(stream) 서비스라고도 부르고, 비연결형 서비스를 UDP 또는 데이터그램 서비스라고도 부른다.


▶ 자신의 IP 주소는 응용 프로그램이 수행되는 컴퓨터의 IP 주소를 말하며, 자신의 포트번호는 이 컴퓨터에서 수행되고 있는 응용 프로그램들 중 본 응용 프로그램을 구분하는 고유번호이다.


▶ 상대방의 IP 주소는 통신하고자 하는 상대방(목적지) 컴퓨터의 IP 주소를 말하며, 상대방의 포트번호는 목적지 컴퓨터내에서 수행중인 여러 응용 프로그램 중 나와 통신할 프로그램을 지정하는 번호이다.


▶ 잘 알려진(well-known) 표준 인터넷 서비스(ftp, mail, http 등)를 처리하는 서버 프로그램은 미리 지정된 포트번호를 사용하고 있다.


▶ 소켓 프로그래밍에서 첫번째로 해야 할 일은 통신 창구 역할을 하는 소켓을 만드는 것으로 이것은 서버와 클라이언트에서 모두 필요한데 이를 위하여 socket() 시스템 콜을 호출한다.


▶socket()이 성공적으로 수행되면 새로 만들어진 소켓번호(int 타입)를 리턴하고 에러가 발생하면 -1이 리턴된다.


▶ socket()의 사용 문법은 다음과 같다.


int socket (

domain, /* 프로토콜 체계 */

type, /* 서비스 타입 */

protocol; /* 소켓에 사용될 프로토콜 */


▶ 소켓은 본래 TCP/IP, 즉 인터넷만을 위하여 정의된 것이 아니며 UNIX 네트웍, XEROX 네트웍 등에서도 사용할 수 있도록 일반적으로 정의된 것이다.


▶ TCP/IP 프로토콜을 사용하려면 소켓을 개설할 때 프로토콜 체계를 인터넷으로 지정하여야 한다.


▶ 이를 위하여 domain을 PF_INET으로 선택하여야 한다.


▶ 한편 domain으로 가질 수 있는 값은 다음과 같다(PF는 Protocol Family를 나타냄).


domain : PF_INET (인터넷 프로토콜 체계 사용)

PF_UNIX (UNIX 방식의 푸로토콜 체계 사용)


PF_NS (XEROX 네트웍 시스템의 프로토콜 체계 사용)


▶ type은 서비스 타입(type of service)을 말하는데, 연결형(스트림) 서비스를 제공하는 소켓을 만들려면 SOCK_STREAM을, 비연결형(데이터그램) 서비스를 선택하려면 SOCK_ DGRAM을 선택하여야 한다.


type : SOCK_STREAM (스트림 방식의 소켓 생성)

  SOCK_DGRAM (데이터그램 방식의 소켓 생성)


▶ protocol은 소켓을 지원하는 프로토콜을 지정하는데 일반적으로 0을 쓰면 시스템이 자동으로 설정해 준다.


▶ 다음은 socket() 시스템 콜을 호출하고 생성된 소켓번호를 출력하는 예제 open_socket.c이다.


▶ 이 프로그램에서는 먼저 /etc/passwd 파일을 열고 리턴된 파일기술자(file descriptor)를 출력한 후, 소켓을 두 개 열어서 소켓번호가 어떤 값인지 확인한다.


/* 스트림형 소켓 열기 */


sd1 = socket(PF_INET, SOCK_STREAM, 0) ;


printf("stream socket descriptor = %d\n", sd1) ;


/* 데이터그램형 소켓 열기 */


sd2 = socket(PF_INET, SOCK_DGRAM, 0) ;


printf("datagram socket descriptor = %d\n", sd2) ; 

/* 또다른 파일 열기 */


close(sd2) ;


close(sd1) ;



▶ 위의 예제 open_socket.c의 실행 결과는 다음과 같다.


stream socket descriptor = 3

datagram socket descriptor = 4


▶ socket() 시스템 콜은 트랜스포트 프로토콜(TCP 또는 UDP)을 선택하여 하나의 소켓을 만드는 함수이다.


▶ 리턴된 소켓번호는 응용 프로그램내에서 생성된 파일과 소켓을 구분하는 유일한 번호인 것을 알 수 있다.


 


2.1.4 소켓주소 구조체


▶ 소켓을 이용할 통신 객체(클라이언트 또는 서버)의 구체적인 주소를 표현하기 위해서는 주소 체계(address family), IP 주소, 포트번호 세 가지가 지정되어야 하며 이 세 가지 주소 정보를 소켓주소(socket address)라고 부른다.


▶ 소켓 프로그래밍에서는 소켓주소를 담을 구조체 sockaddr를 아래와 같이 정의하였으며 이것은 2바이트의 address family와 14바이트의 주소(IP 주소 + 포트번호)로 구성되어 있다.


struct sockaddr {

u_short sa_family; /* address family */


char sa_data[14]; /* 주소 */


};


▶ 그런데 위에 정의된 sockaddr 소켓주소 구조체에 IP 주소, 포트번호 등을 직접 쓰거나 읽기가 불편하므로 인터넷 프로그래밍에서는 sockaddr 구조체를 사용하는 대신 4바이트의 IP 주소와 2바이트의 포트번호를 구분하여 지정할 수 있는 인터넷 전용 소켓주소 구조체인 sockaddr_in을 주로 사용한다.


▶ sockaddr_in에서는 다시 32비트의 IP 주소를 저장하는 구조체 in_addr를 사용하고 있으며 sockaddr_in과 sockaddr의 호환성을 위하여 두 구조체의 전체 크기는 16바이트로 같도록 하였다.


struct in_addr {

u_long s_addr; /* 32비트의 IP 주소를 저장할 구조체 */


}; 

struct sockaddr_in {


short sin_family; /* 주소 체계 */


u_short sin_port; /* 16비트 포트번호 */


struct in_addr sin_addr; /* 32비트 IP 주소 */


char sin_zero[8]; /* 16바이트 크기를 맞추기 위한 dummy */


};


 


▶ 위에서 주소 체계 sin_family로 선택할 수 있는 것은 다음과 같으며 인터넷에서는 항상 인터넷 주소 체계(AF_INET)를 선택하여야 한다.


sin_familly : AF_INET (인터넷 주소 체계)

AF_UNIX (유닉스 파일 주소 체계)


AF_NS (XEROX 주소 체계)


▶ 소켓주소의 주요 내용은 IP 주소와 포트번호인데, 소켓주소는 응용 프로그램이 자신의 소켓주소(local address)를 표현하는 데에도 사용되며 상대방 프로세스의 소켓주소(remote address)를 표현할 때도 사용된다(즉, 2.1.3절의 ②+③ 또는 ④+⑤를 각각 나타내기 위해 소켓주소 구조체가 사용된다).


2.1.5 소켓 프로그래밍 절차


▶ 소켓 프로그래밍도 대표적인 네트웍 프로그래밍으로서 1.3절에서 설명한 클라이언트-서버 통신 모델로 구현된다.


▶ 소켓을 이용한 클라이언트와 서버의 프로그래밍 절차를 간략히 설명하고, 2.3절과 2.4절에서 클라이언트와 서버 프로그램의 작성 과정을 상세히 설명하겠다.


▶ 그림 2-4에 클라이언트와 서버가 TCP(스트림형 또는 연결형) 소켓을 만들고 서로 연결한 다음 데이터를 송수신하고 소켓을 종료하는 절차를 나타냈다.


▶ 클라이언트-서버 통신 모델에서는 항상 서버 프로그램이 먼저 수행되고 있어야 한다.


▶ 서버는 socket()을 호출하여 통신에 사용할 소켓을 하나 개설하고 이때 리턴된 소켓번호와 자신의 소켓주소 (2.1.3절의 ②+③)를 bind()를 호출하여 서로 연관시켜 둔다.


▶ 서버에서 bind()가 필요한 이유는 소켓번호는 응용 프로그램이 알고 있는 통신 창구 번호이고, 소켓주소(②+③)는 네트웍 시스템(즉, TCP/IP)이 알고 있는 주소이므로 이들의 관계를 묶어 두어야(bind) 응용 프로세스와 네트웍 시스템간의 패킷 전달이 가능하기 때문이다(bind()의 자세한 사용법은 2.4.1절에서 설명함).


▶ 다음에 서버는 listen()을 호출하여 클라이언트로부터의 연결요청을 기다리는 수동 대기모드로 들어간다.


▶ 클라이언트로부터의 연결요청이 왔을 때 이를 처리하기 위하여 accept()를 호출한다.


▶ 서버는 accept() 시스템 콜에서 기다리고 있다가 클라이언트가 connect()를 호출하여 접속요구를 해오면 이를 처리한다.


▶ 연결이 성공적으로 이루어지면 서버는 클라이언트와 데이터를 송수신할 수 있게 된다.


▶ 한편 클라이언트는 socket()을 호출하여 소켓을 만든 후 bind()를 부를 필요 없이, 서버에게 연결요청을 보내기 위하여 connect()를 호출한다.


▶이때 클라이언트는 접속할 상대방 서버의 소켓주소(④+⑤) 구조체를 만들어 connect()의 함수 인자로 주어야 한다.


▶ 서버와 연결이 이루어지면 (즉, connect()문이 성공적으로 리턴되면) 서버와 데이터를 송수신할 수 있다.

 



▶ 클라이언트에서 bind()를 호출할 필요가 없는 이유는, 클라이언트 프로그램은 서버 프로그램과 달리 자신이 사용하는 IP 주소나 포트번호를 다른 클라이언트 또는 서버가 미리 알고 있을 필요가 없기 때문이다.


▶ 서버의 응용 프로그램은 자신이 사용하고 있는 포트번호를 통하여 클라이언트들의 서비스를 처리해야 하므로, 응용 프로그램이 소켓번호와 소켓주소를 bind()하는 것이 필수적이다.


▶ 클라이언트는 포트번호를 임의로 사용해도 되기 때문에 포트번호를 특정한 값으로 bind()시켜 두는 것이 필요 없다.


▶ 클라이언트는 오히려 bind()를 사용하는 것이 클라이언트 프로그램의 범용성을 떨어뜨리게 된다. 왜냐하면 같은 포트번호를 사용하는 클라이언트 프로그램들이 하나의 컴퓨터에서 두 개 이상 실행되면 에러가 발생하기 때문이다.

'IT' 카테고리의 다른 글

IT업계 수익모델 총정리  (0) 2017.01.24
301 redirect, 302 redirect.  (0) 2017.01.24
소켓 통신. 네트워크 프로그래밍.  (0) 2017.01.18
UI 라이브러리  (0) 2016.08.31
저장 버튼(save button) 더블클릭 방지.  (1) 2015.04.28
Posted by 당양부부34

블로그 이미지
주요 토렌트를 블로깅하고 있습니다. 토렌트 순위 등은 다른 사이트를 찾아보세요. 주요 웹툰 순위도 게재했어요 경제를 좋아하는 일산의 행복한 프로그래머입니다.
당양부부34
Yesterday
Today
Total

달력

 « |  » 2024.4
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함