소켓 통신 #2 - AF_INET 사용하기 (2)
- by Tapito
이번에는 서버가 되어 접속 요청을 받아들여보겠습니다.
클라이언트에서는 접속 대상의 sockaddr_in 구조체 세팅 - socket() 함수 - connect() 함수의 3단계로 접속이 진행된 반면,
서버는 자신의 sockaddr_in 구조체 세팅 - socket() 함수 - bind() 함수 - listen() 함수 - accept() 함수의 5단계로 접속이 진행됩니다.
1단계. sockaddr_in 구조체 설정하기
sockaddr_in 구조체 설정은 클라이언트와 크게 다르지 않습니다. 다만 자신의 IP 주소를 명시하지 않는다는 차이가 있습니다.
/* 사용 예 */ struct sockaddr_in sockaddr_internet; /* 주소 체계로서 IPv4를 사용하는 인터넷망에 접속 */ sockaddr_internet.sin_family = AF_INET; /* 접속할 대상을 지정하지 않음 */ serveraddr.sin_addr.s_addr = inet_addr(INADDR_ANY); /* 포트 번호는 1435 */ serveraddr.sin_port = htons(1435);
2단계. socket 생성하기
네트워크에 접속하기 위한 소켓을 생성합니다. 이 역시 클라이언트 측에서 생성한 방식과 같습니다.
/* 사용 예 */ SOCKET sock; /* 인터넷에 접속하여 스트림 방식으로 입출력하는 소켓 생성 */ sock = socket(AF_INET, SOCK_STREAM, 0); /* 소켓 만들기에 실패 시 INVALID_SOCKET이 반환 */ if(sock == INVALID_SOCKET) printf("Invalid Socket");
3단계. 생성한 소켓을 접속을 받는 용도로 지정
bind 함수는 생성된 소켓에 지역 IP 주소와 포트 번호를 연결시켜 서버용 소켓으로 만들어주는 역할을 합니다.
int bind(SOCKET s, const struct sockaddr * name, int namelen);
s: 서버용으로 사용할 소켓입니다.
name: 자기 자신의 sockaddr 구조체입니다.
namelen: 여기에서는 sockaddr_in 구조체의 크기입니다.
/* 사용 예 */ int state; state = bind(sock , (struct sockaddr *)&sockaddr_internet, sizeof(sockaddr_in)); if (state == SOCKET_ERROR) printf("Socket Error");
4단계. 접속이 들어올때까지 대기
서버로서 갖추어야 할 준비는 모두 끝났습니다. 이제 손님이 접속할 때까지 계속 기다리기만 하면 됩니다. 이 역할을 하는 함수는 listen() 함수입니다.
int listen(SOCKET s, int backlog);
s: 서버용으로 쓰는 소켓입니다.
backlog: 최대 대기자 수에 해당하는 정수 값입니다. 이 값의 기준은 따로 정해지지 않았고 경험적으로 5 정도면 적당하다고 알려져 있습니다.
/* 사용 예 */ int state; /* 접속자가 들어올때까지 내부적으로 무한루프를 돌리며 계속 이 단계에서 머물게 될 것입니다. */ state = listen(sock, 5); /* listen도 오류시 SOCKET_ERROR를 반환합니다. 접속자 1명을 성공적으로 받아들였다면 0이 반환될 것입니다. */ if(state == SOCKET_ERROR) printf("Socket Error");
5단계. 자신에게 접속한 유저의 sockaddr_in 얻기
서버로 열어두고 접속을 기다렸으면 자신에게 들어온 유저가 누구인지를 알 필요가 있습니다. 클라이언트가 connect 함수로 자신에게 접속하면서 클라이언트 자신의 sockaddr_in 구조체의 내용도 서버에게 전해지는데 이 역할은 accept 함수에서 수행합니다.
SOCKET accept(SOCKET s, struct sockaddr * addr, int * addrlen);
s: 서버용으로 쓰고 있는 소켓입니다.
addr: 접속 유저에 대한 정보를 저장할 sockaddr 구조체 포인터입니다.
addrlen: 접속된 유저에 대한 정보가 몇 바이트인지도 이 변수를 통해 얻을 수 있습니다.
반환 값으로 접속자 1인에 대한 소켓이 반환됩니다.
/* 사용 예 */ SOCKET sockClient; struct sockaddr_in sockaddrClient; int sockaddrSize = 0; sockClient = accept(sock, (struct sockaddr *)&sockaddrClient, &sockaddrSize); if(sockClient == INVALID_SOCKET) printf("Invalid Socket"); else printf("접속자 IP는 %s이고 구조체 크기는 %d바이트입니다.", inet_ntoa(sockaddrClient.sin_addr), sockaddrSize);
'Programming Language > C&C++' 카테고리의 다른 글
소켓 통신 #2 - AF_INET 사용하기 (4) (0) | 2014.09.20 |
---|---|
소켓 통신 #2 - AF_INET 사용하기 (3) (0) | 2014.09.20 |
소켓 통신 #2 - AF_INET 사용하기 (1) (0) | 2014.09.19 |
소켓 통신 #1 - 소켓 통신에 쓰이는 구조체 (2) | 2014.09.19 |
C++11에서 추가된 클래스 - thread (0) | 2014.04.17 |