드디어 중요한 accept 함수를 다루게 되었습니다. 이 함수는 TCP연결방식에서 서버측에서만 쓰이는 함수입니다. 클라이언트에서는 사용하지 않는 함수죠. 이 함수가 호출되면 클라이언트의 연결요청을 기다렸다가 요청을해오면 수락해서 서버-클라이언트간의 연결 고리를 만드는 함수입니다.
전에 TCP를 전화기에 비유했는데 이 함수를 전화기에 비유해보자면 '전화가 걸려오면 전화를 받는 기능' 을 한다고 말할 수 있습니다. 물론 여기에서는 클라이언트가 연결요청을 하기전에 accept 함수를 호출한 상태여야 하겠지만 말예요. 함수 원형을 살펴볼까요?
SOCKET accept(
SOCKET s,
struct sockaddr* addr,
int* addrlen
);
우선 리턴타입이 SOCKET형입니다. 이 함수는 연결요청을 한 클라이언트와 서버간의 연결고리 기능을 하는 소켓을 리턴하는 것이죠. 서버는 이 클라이언트로 메시지나 데이터를 전송하기 위해서 이 함수가 리턴하는 SOCKET을 쭈욱 사용하게 됩니다. 그리고 에러가 났을땐 INVALID_SOCKET 을 리턴합니다. 리턴값을 확인해보고 에러가 나오면 적당히 처리해 줘야하며, 에러가 나지 않았을땐 후에 클라이언트와의 통신을 위해서 소켓을 잘 보관해 두어야 합니다.
첫번째 인수도 SOCKET을 받는데 listen 함수에서 파라미터로 넣었던 서버소켓을 여기에 넣어줍니다. 그리고 sockaddr 구조체의 포인터인 addr은 출력용 파라미터인데 연결요청을 해온 클라이언트의 정보가 채워져서 들어오게 됩니다. 마찬가지로 3번째 파라미터인 addrlen도 출력용 파라미터인데 여기엔 두번째 파라미터의 크기가 담겨지게 됩니다.
여기서 주의할점은 accept함수는 '블록함수'라는 점입니다. 블록함수란 쉽게말해 리턴되지 않는 함수라는 것이죠. 우리가 C를 배울때 사용했던 getch나 getchar같은 함수가 블록함수라고 생각할 수 있습니다. 사용자의 입력이 없으면 리턴하지 않고 계속 대기하다가 사용자가 입력을 마치면 그제서야 리턴을 하게되고 다음처리를 할 수 있게되는거죠. 우리가 그 함수를 사용할때 어땟나요? 사용자의 글씨, 또는 메시지를 입력받기에는 적당했지만 게임같이 실시간으로 입력과 출력이 처리되어야 하는 프로그램( 슈팅게임같은 )에서는 사용할 수 없었죠? 바로 함수가 리턴되지 않고 해당일을 처리할 때까지 블록상태( 대기상태 )로 들어가기 때문입니다.
accept 함수도 마찬가지로 이 함수를 호출한뒤에 클라이언트의 연결요청이 들어올때까지 리턴하지않고 무작정 대기하게 됩니다. 서버프로그램은 여러가지를 처리해야 하는데 단지 클라이언트의 연결을 수락하기 위해서만 멈춰있다면 큰일이겠지요. 만약 클라이언트가 연결요청을 해오지 않는다면 서버 프로그램은 단지 장식용이 되어버릴테니까요.
소켓 프로그래밍에선 이런 블록함수들이 많이 있습니다. accept함수가 그렇고 connect함수, 데이터를 주고받는 send/recv함수들이 그렇죠. 그외에도 여러가지..
이를 해결하기 위해서는 멀티스레드 방식을 생각하실지도 모르겠지만 그보다 더 깔끔한 방법이 있습니다. 윈속에서는 이런 블록함수의 문제를 해결하기 위해서 비동기 윈속함수를 사용할 수 있는데 윈도우 프로그래밍처럼 메시지를 사용하는 방법입니다. 이는 다음에 비동기 윈속을 다룰때 설명드리기로 하고 우선은 이 함수는 '클라이언트의 연결요청을 수락하는 함수이다' 라고만 알아두세요.
- Reference
'[ Windows Program ] > Windows API' 카테고리의 다른 글
비동기 소켓 - WSAAsyncSelect (1) | 2011.03.07 |
---|---|
데이터 전/수송 함수인 send/recv (0) | 2011.03.07 |
클라이언트의 접속을 가능하게 하는 listen 함수 (0) | 2011.03.07 |
주소할당 함수 bind의 사용 (0) | 2011.03.07 |
주소 사용법( 주소체계, 바이트순서 ) (0) | 2011.03.07 |