U E D R S I H C RSS
ID
Password
Join
위인과 만나거든 너의 좋은 인상을 남기도록 하되, 소인과 만나거든 그 사람의 좋은 인상만을 남기도록 하라. ―사뮤엘 테일러 콜리지

요약 #

이 아티클은 소켓의 ovarlapped I/O 속성과 블록/넌블록킹 모드 간의 차이점에 대해서 설명한다.

보다 많은 정보 #

소켓이 생성될 때에는 기본적으로 그것은 블록킹 소켓으로 설정된다. FIONBIO 옵션과 같이 ioctlsocket()함수를 사용하거나, WSAEventSelect() 또는 WSAAsyncSelect()를 사용하면 소켓은 블록모드에서 넌블록모드로 바뀌게 된다. 만약 윈속이 send/recv 처리시 즉시 종료할 수 없다면, 호출은 SOCKET_ERROR를 반환하고 WSAGetLastError() 함수로 에러코드를 검사하면 WSAEWOULDBLOCK 값이 나오게 된다. (이것은 넌블록킹 모드일 경우를 말한다. 블록킹 소켓이면 명령이 끝날 때까지 기다리게 된다.)

The socket overlapped I/O attribute is different from the socket's blocking or non-blocking mode. Although the current Winsock implementation requires overlapped I/O attribute for non-blocking socket mode, they are conceptually independent and their programming model is different too. To create a socket with the overlapped I/O attribute, you can either use the socket API or the WSASocket API with the WSA_FLAG_OVERLAPPED flag set. If an overlapped I/O operation can not complete immediately, the call fails and WSAGetLastError or GetLastError return WSA_IO_PENDING or ERROR_IO_PENDING, which is actually the same define as WSA_IO_PENDING. For additional information, please see the following article in the Microsoft Knowledge Base:

Q179942 INFO: WSA_FLAG_OVERLAPPED Is Needed For Non-Blocking Sockets

Please note that once a socket is created, there is no way to change the socket overlapped attribute. However, you can call the setsockopt API with SO_OPENTYPE option on any socket handles including an INVALID_SOCKET to change the overlapped attributes for all successive socket calls in the same thread. The default SO_OPENTYPE option value is 0, which sets the overlapped attribute. All non-zero option values make the socket synchronous and make it so that you cannot use a completion function.

By setting a socket's overlapped I/O attribute it doesn't mean that the socket will perform an overlapped I/O operation. For example, if you specify NULL for both the completion function and the overlapped structure in WSARecv and WSASend, or you simply call recv or send functions, they will complete in a blocking fashion. To make sure the I/O is performed in an overlapped fashion you need to provide an overlapped structure in your I/O function, depending on the function you use.

Overlapped I/O #

윈속 1에서는 소켓 API를 사용하여 overlapped 소켓을 생성하고 소켓 핸들에 ReadFile(), ReadFileEx(), WriteFile(), WriteFileEx() Win32 API를 사용하여 ovelapped 입출력을 수행했다. 윈속 2에서는 WSA_FLAG_OVERLAPPED 옵션을 가진 WSASocket() 함수를 사용하여 Overlapped 소켓을 생성하거나 또는 간단히 소켓 API를 사용하여 소켓을 생성할 수 있다. overlapped 입출력을 초기화하기 위해서는 위에서 열거한 Win32 화일 입출력 함수를 사용하거나 WSASend(), WSASendTo(), WSARecv(), WSARecvFrom()함수를 사용하면 된다.

만약 TCP 스택의 받기/보내기 버퍼를 0으로 만들기 위해 SO_RCVBUF/SO_SNDBUF 옵션을 사용한다면, 입출력을 수행할 때 인자로 넘겨준 포인터 변수를 직접적으로 소켓버퍼 대신으로 사용하라는 의미가 된다. 따라서 overlapped 소켓 I/O 의 넌블록으로 처리할 수 있는 장점에 덧붙여서, 각각의 입출력 호출때마다 사용자 버퍼(인자로 넘겨준 포인터를 말한다)와 TCP 스택 버퍼(소켓 버퍼)간에 버퍼 복사본을 저장함으로써 더 나은 성능을 얻을 수 있다. But you have to make sure you don't access the user buffer once it's submitted for overlapped operation and before the overlapped operation completes.

To determine whether the overlapped I/O operation is completed, you can use one of the following options:

  • You can provide an event handle in an overlapped structure used in the I/O call and wait on the event handle to signal.
  • Use GetOverlappedResult or WSAGetOverlappedResult to poll the status of the overlapped I/O operation. On Windows NT, you can specify NULL as the event handle in the overlapped structure. However, on Windows 95 the overlapped structure needs to contain a manual reset event handle.
  • Use ReadFileEx, WriteFileEx, WSARecv, WSARecvFrom, WSASend, or WSASendTo and choose to provide a completion function to be called when the overlapped I/O operation has completed. If you use the completion function approach, at some point after you have issued the overlapped I/O operation you need to issue a Win32 wait function or a WSA version of wait function to wait on a non-signaled handle to put your current thread into an alertable wait state. When the overlapped I/O operation completes, your completion function is called, your wait function is going to return WAIT_IO_COMPLETION, and your alertable wait thread wakes up.

소켓과 결합하는데 Overlapped I/O 속성을 지정하면서 GetQueuedCompletionStatus()를 사용하라. (이것은 Windows NT I/O Completion Port(IOCP)를 사용하는 것을 의미한다.)

IOCP를 사용한다면, 소켓 입출력을 수행하는데 있어서 완료 루틴을 제공할 필요가 없고, 이벤트 핸들이 시그널되기를 기다릴 필요도 없으며, you don't need to supply a completion function, wait on an event handle to signal, or poll the status of the overlapped operation. Once you create the IOCP and add your overlapped socket handle to the IOCP, you can start the overlapped operation by using any of the I/O APIs mentioned above (except recv, recvfrom, send, or sendto). You will have your worker thread block on GetQueuedCompletionStatus API waiting for an I/O completion packet. When an overlapped I/O completes, an I/O completion packet arrives at the IOCP and GetQueuedCompletionStatus returns.

IOCP는 Windows NT 운영체계에서 제공하는 overlapped I/O 명령상에서 매우 간단한 쓰레딩과 블럭킹을 사용하여 확장가능한, 고출력의 서버를 제작하기 위한 장치이다. 따라서 Overlapped 소켓 I/O와 IOCP를 같이 사용하면 괜찮은 성능 이익을 얻을 수 있다.

블록킹/넌블록킹 모드 #

When a socket is created, by default it is a blocking socket. Under blocking mode socket I/O operations, connect and accept operations all block until the operation in question is completed. To change the socket operation mode from blocking mode to non-blocking mode, you can either use WSAAsyncSelect, WSAEventSelect, or the FIONBIO command in the ioctlsocket API call.

WSAAsyncSelect maps socket notifications to Windows messages and is the best model for a single threaded GUI application.

WSAEventSelect uses WSAEnumNetworkEvents to determine the nature of the socket notification on the signaling event and maps socket notifications by signaling an event. This is a useful model for non-GUI applications that lack a message pump, such as a Windows NT service application.

The FIONBIO command in the ioctlsocket API call puts the socket into non- blocking mode as well. But you need to poll the status of the socket by using the select API.


Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2010-10-28 12:42:54
Processing time 0.3432 sec