#서버
1. 소켓 생성
나중에 클라이언트로부터의 연결 요청을 받을 수 있도록 socket 함수를 이용하여 네트워크 연결 장치인 소켓을 생성한다.
아래 예는 TCP용 전화기를 준비한 경우라 할 수 있다. 즉, TCP 통신이 가능한 TCP용 소켓을 생성하였다고 생각하면 된다.
int s_socket = socket(PF_INET, SOCK_STREAM, 0);
2. 연결 요청을 수신할 주소 설정
클라이언트로부터의 연결 요청을 받을 서버 IP주소와 포트를 설정하고 있다.
여기서 IP주소는 INADDR_ANY, 포트번호는 9000번으로 설정하고 있는데, 이는 현재 서버의 9000번 포트를 목적지로 하는 모든 연결 요청에 대해 처리하겠다는 의미이다. IP주소로 INADDR_ANY를 설정한 이유는 한 컴퓨터에 여러장의 랜카드가 장착되어 있어서 여러개의 IP 주소가 할당되고, 서버 응용프로그램은 이들 IP를 통해 들어오는 모든 연결요청을 받아 처리해야 하기에 사용한 것이다.
memset(&s_addr, 0, sizeof(s_addr));
s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
s_addr.sin_family = AF_INET;
s.addr.sin_port = htons(PORT);
3. 소켓을 포트에 연결
1번에서 생성한 소켓을 2번에서 설정한 주소에 연결한다. 여기서는 소켓을 포트 9000번에 연결하고 있다.
if(bind(s_socket, (struct sockaddr *)&s_addr, sizeof(s_addr))==-1) {
printf("can't bind\n");
return -1;
}
4. 커널에 개통을 요청
해당 소켓으로 통신이 이루어지도록 운영체제에 개통을 요청하고 있다.
운영체제는 이 시점부터 다른 호스트에서 포트번호 9000번으로 요청하는 연결을 받아들이기 시작한다.
우리가 전화기를 전화기 콘센트에 물리적으로 연결하고서 전화국에 개통을 요청해야 외부에서 오는 전화를 받을 수 있는 것과 마찬가지 이치이다. 다시말해서 전화국 역할을 하는 운영체제에 개통을 요청하는 단계이다.
if(listen(s_socket, 5) == -1) {
printf("listen fail\n");
return -1;
}
5. 클라이언트로부터 연결 요청을 수신
클라이언트로부터 연결 요청을 받아들이는 코드이다. 전화오기를 기다리다가 비로소 수화기를 들어받는 단계이다.
클라이언트로부터의 연결 요청을 1번에서 생성한 소켓 s_socket으로 받으면, 운영체제에서는 클라이언트와 자료를 송수신할 때 사용할 소켓 c_socket을 반환한다. 이후에는 연결소켓 c_socket을 통해 클라이언트와 자료를 송수신한다.
int len = sizeof(c_addr);
int c_socket = accept(s_socket, (struct sockaddr *)&c_addr, &len);
6. 클라이언트에게 서비스를 제공
int n = strlen(buffer);
write(c_socket, buffer, n);
#클라이언트
1. 소켓생성
서버와 통신할 소켓을 생성
c_socket = socket(PF_INET, SOCK_STREAM, 0);
2. 연결할 주소를 설정
연결할 서버의 주소를 구조체 변수 c_addr에 설정하고 있다. 클라이언트 프로그램에서 연결할 서버의 IP주소는 127.0.0.1 자기자신으로,
포트번호는 9000번으로 각각 설정하고 있다.
#define PORT 9000
#define IPADDR "127.0.0.1"
memset(&c_addr, 0, sizeof(c_addr));
c_addr.sin_addr.s_addr = inet_addr(IPADDR);
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(PORT);
3. 소켓을 서버에 연결
c_socket으로 변수 c_addr에 설정된 주소에 연결을 시도한다. 이와 관련해서 서버와의 연결은 커널 내부에서 3-way handshaking을 거쳐 이루어진다. 클라이언트는 클라이언트 커널에서 서버연결에 사용할 포트(예: 2345번 포트)를 결정하기 때문에 클라이언트 프로그램에서는 포트번호를 특별히 지정하지는 않는다.
if(connect(c_socket, (struct sockaddr *) &c_addr, sizeof(c_addr))==-1) {
printf("Can not connect\n");
close(c_socket);
return -1;
}