IT_Programming/Network Programming

[Windows_WinSock2] 조건부 Accept & Scatter/Gather I/O

JJun ™ 2009. 11. 12. 15:45

-------------------------------------------------------------------------------------------------

                                                                                                   참조: TCP/IP 소켓 프로그래밍

-------------------------------------------------------------------------------------------------

 

1. 조건부 억셉트
     : 클라이언트의 접속 허용 여부를 설정할 수 있다.


  1) SOCKET WSAAccept (
                                         SOCKET s,                                  ... ①
                                         struct sockaddr FAR *addr,            ... ②
                                         LPINT addrlen,                             ... ③
                                         LPCONDITIONPROC lpfnCondition, ... ④
                                         DWORD dwCallBackData                ... ⑤
                                 );

 

     ① Listen Socket Handle
     ② Accept 될 상대편 주소의 구조체
     ③ ② 구조체의 길이
     ④ 조건부 Accept 함수 포인터
     ⑤ 조건부 Accept 함수가 호출될 때 사용

 

     : 조건부 Accept 함수에서 CF_ACCEPT를 리턴 시키면 클라이언트로부터 접속을 받아들이고,
       CF_REJECT를 리턴하게 되면 해당 접속은 거절되어 무시되고, WSAECONNREFUSED 오류 코드를
       발생시킨다.

 

     : WSAAccept() 함수는 동작시키는 스레드가 실행하기 때문에 빨리 실행하고 리턴해야 한다.
       따라서 일단 CF_DEFFER를 리턴해서 나중에 접속을 받아들일지 거절할 것인지를 알려주겠다고
       하면 된다. (이 경우 일단 Accept 동작은 무시하게 되고 접속 허용 여부를 다시 결정한다.)

 

     : 블로킹 모드    -  접속 대기 큐가 비었다면, accept와 마찬가지로 블로킹 되어 멈춰있다.

       비블로킹 모드 -  접속 대기 큐가 비었다면, WSAEWOULDBLOCK 오류를 리턴한다.

 


  2) CONDITIONPROC 함수 (④)
     - int CALLBACK ConditionFunc (
                                                        IN LPWSABUF lpCallerId,         ... ①
                                                        IN LPWSABUF lpCallerData,     ... ②
                                                        IN OUT LPQOS lpSQOS,         ... ③
                                                        IN OUT LPQOS lpGQOS,         ... ④
                                                        IN LPWSABUF lpCalleeId,        ... ⑤
                                                        OUT LPWSABUF lpCalleeData, ... ⑥
                                                        OUT GROUP FAR *g,               ... ⑦
                                                        IN DWORD dwCallbackData      ... ⑧
                                                 );
 
     ① WSABUF의 포인터. WSABUF 구조체 안의 멤버 자료 buf에 SOCKADDR 구조체를 담고 있어
        접속을 시도한 클라이언트의 주소 정보를 얻어낼 수 있다.

 

     ② 연결 시점에서 받은 데이터가 있다면 WSABUF의 포인터로 들어온다.
     ③ references the FLOWSPEC structures for socket s specified by the caller,
        one for each direction, followed by any additional provider-specific parameters.

 

     ④ The lpGQOS parameter is reserved, and should be NULL.

     ⑤ 서버 자기 자신의 주소에 대한 정보가 담겨있다. ①과 마찬가지로 데이터를 얻을 수 있다.

     ⑥ 접속 시점에서 클라이언트로 보낼 데이터를 설정하는 인자.
        TCP에서는 이미 조건부 함수가 호출되기 전에 클라이언트의 접속이 완료되므로 의미가 없다.
    
     ⑦ Socket Group
     ⑧ WSAAccept 함수를 호출할 때 마지막에 넣었던 콜백 데이터. (추가적인 자료)

  


  3) WSABUF 구조체: 버퍼 정보를 담기 위한 구조체
 
     typedef struct __WSABUF
     {
        u_long   len;     // 버퍼 사이즈
        char FAR *buf;  // 버퍼 시작 주소
     } WSABUF, FAR *LPWSABUF;

 
  

 


2. scatter/gather I/O
   : Winsock2에서는 WSASend() 함수나 WSASendTo() 함수 그리고 WSARecv() 함수나 WSARecvFrom()

     함수에서 보내거나 받기 위한 버퍼를 배열로 인자를 넣을 수 있는데 이를 scatter/gather I/O 또는

     vectored I/O 라고 한다.

 

   : 분리된 버퍼들에 차례로 데이터를 받게 할 수 있는 기법으로, 분리된 버퍼들을 한 곳에 복사하는

     임시 버퍼를 사용하지 않고, 한 번에 보내고 받을 수 있어 네트워크 성능 향상을 꾀할 수 있다.


   1) int WSASend (
                 SOCKET                                                  s,                            ... ①
                 LPWSABUF                                               lpBuffers,                  ... ②
                 DWORD                                                    dwBufferCount,           ... ③
                 LPDWORD                                                 lpNumberOfBytesSent, ... ④
                 DWORD                                                    dwFlags,                   ... ⑤
                 LPWSAOVERLAPPED                                   lpOverlapped,            ... ⑥
                 LPWSAOVERLAPPED_COMPLETION_ROUTINE  lpCompletionROUTINE ... ⑦
      );


     ① 접속된 소켓을 가리키는 소켓 기술자.
     ② WSABUF 구조체의 포인터.
     ③ lpBuffer 배열로 지정된 WSABUF 구조체의 갯수.
     ④ 이 함수의 호출로 인해서 전송된 바이트의 개수를 포인트 합니다.
        (한 번의 호출로 보내진 양을 나타낸다.)

 

     ⑤ 어떠한 방식으로 전송을 수행 할 것인지 설정하는 플래그.

 

     <Overlapped 이벤트로 시그널을 받을 것인지, 완료 루틴(⑦)으로 나중에 호출할 것인지를 결정>
     ⑥ WSAOVERLAPPED 구조체의 포인터. (Non-Overlapped 소켓에 대해서는 무시됩니다.)   
     ⑦ 전송연산이 완료되었을 때 호출되는 전송완료 루틴에 대한 포인터입니다.
        (Non-Overlapped 소켓에 대해서는 무시됩니다.)


   2) int WSARecv (
              SOCKET                                                 s,                   ... ①              
              LPWSABUF                                              lpBuffers,            ... ②
              DWORD                                                   dwBufferCount,        ... ③
              LPDWORD                                                lpNumberOfBytesRecvd, ... ④
              LPDWORD                                                lpFlags,              ... ⑤
              LPWSAOVERLAPPED                                  lpOverlapped,         ... ⑥
              LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE ... ⑦
      );

 

     ① 접속된 소켓의 기술자.
     ② WSABUF 구조체의 배열 포인터로, 각각의 WSABUF 구조체는 데이터를 담은 버퍼와 버퍼의 길이를

         가지게 됩니다.

 

     ③ lpBuffer 배열에 있는 WSABUF 구조체( 배열의 엘리먼트)의 개수
     ④ 데이터 수신 작업이 바로 완료된 경우, 이 함수의 호출로 읽어낸 데이터의 바이트 수를 포인트 합니다.

         (한 번의 호출로 보내진 양을 나타낸다.)

 

     ⑤ 어떠한 방식으로 이 함수를 호출할 것인가를 나타내는 플래그.

 

     <Overlapped 이벤트로 시그널을 받을 것인지, 완료 루틴(⑦)으로 나중에 호출할 것인지를 결정>
     ⑥ WSAOVERLAPPED 구조체의 포인터. (Non-Overlapped 소켓에 대해서는 무시됩니다.)
     ⑦ 수신 작업이 완료되었을 때 호출될 완료 루틴의 포인터. 

         (Non-Overlapped 소켓에 대해서는 무시됩니다.)


   3) 사용 예 (WSASend())

        char *pHeader;                                        char *pHeader;
        char *pContents;                                      char *pContents;

             ...                                       →                       ...    
       
        char buf[100];                                          WSABUF wbuf[2];
        memcpy(buf, pHeader, 10);                       wbuf[0].buf = pHeader;
        memcpy(buf, pContents, 30);                     wbuf[0].len = 10;
                                                                       wbuf[1].buf = pContents;
        send(s, buf, 40, 0);                                    wbuf[1].len = 30;

                                             

                                                                       DWORD dwSent;
                                                                       WSASend(s, wbuf, 2, &dwSent, 0, NULL, NULL);

 
     사용 예 (WSARecv())

     : 일일이 분리된 버퍼에 나누어 복사할 필요 없이 바로 각 버퍼에 담을 수 있다.

      

       char *pHeader = new char[10];

       char *pContents = new char[30];

                    ...

       WSABUF wbuf[2];

       wbuf[0].buf = pHeader;
       wbuf[0].len = 10;
       wbuf[1].buf = pContents;
       wbuf[1].len = 30;

      

       DWORD dwRead;

       WSARecv(s, wbuf, 2, &dwRead, 0, NULL, NULL);


-------------------------------------------------------------------------------------------------

StdAfx.cpp
0.0MB
StdAfx.h
0.0MB
WSAAccept.cpp
0.01MB