서버 프로그래밍 소감 (4) - socket을 비차단 모드로 설정하는 방법
SOCKET WSAAPI socket(
_In_ int af,
_In_ int type,
_In_ int protocol
);
SOCKET WSASocket(
_In_ int af,
_In_ int type,
_In_ int protocol,
_In_ LPWSAPROTOCOL_INFO lpProtocolInfo,
_In_ GROUP g,
_In_ DWORD dwFlags
);
linux 플랫폼에서 socket () 함수를 이용하여 socket을 만들 때 지정한 socket은 비동기적입니다.
int socket(int domain, int type, int protocol);
type 매개변수에서 SOCK_ 설정NONBLOCK 로고는 다음과 같습니다.
int s = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
2. 또한 윈도우즈와 linux 플랫폼에서 accept () 함수가 되돌아오는 socekt도 막힌다. linux는 되돌아오는 socket을 비막힘 모드로 설정할 수 있는 accept4 () 함수를 제공한다.
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
accept4 () 마지막 매개변수 플래그를 SOCK_로 설정하면NONBLOCK이면 됩니다.
3. socket을 만들 때 socket을 비차단 모드로 설정하는 것 외에 다음 API 함수를 통해 설정할 수 있습니다.
linux 플랫폼에서 fcntl () 또는 ioctl () 함수를 호출할 수 있습니다. 예는 다음과 같습니다.
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);
ioctl(sockfd, FIONBIO, 1); //1: 0:
참조:http://blog.sina.com.cn/s/blog_9373fc760101i72a.html
하지만 인터넷에도 (링크:http://blog.csdn.net/haoyu_linux/article/details/44306993), linux에서 fcntl () 를 호출하여 socket을 비차단 모드로 설정하면 O_ 뿐만 아니라NONBLOCK 모드, 데이터 수신 및 전송 시 MSG_ 필요DONTWAIT 로고, 즉 recv,recvfrom,send,sendto 데이터에서 flag를 MSG_로 설정합니다DONTWAIT.이런 이중 설정을 할 필요가 있는지 필자는 그럴 필요가 없다고 생각한다.linux man 매뉴얼의 recv () 함수에 대한 설명에서 MSG_DONTWAIT 지침은 다음과 같습니다.
Enables nonblocking operation; if the operation would block, the call fails with the error EAGAIN or EWOULDBLOCK (this can also be enabled using the O_NONBLOCK flag with the F_SETFL fcntl(2)).
이 단락을 통해recv() 함수를 설정한flags를 통해 MSG_DONTWAIT, 또는 fcntl() 함수를 통해 O_ 설정동시에 설정하지 않고 NONBLOCK ID입니다.
윈도우즈에서 ioctlsocket 함수를 호출할 수 있습니다.
int ioctlsocket(
_In_ SOCKET s,
_In_ long cmd,
_Inout_ u_long *argp
);
cmd 매개 변수를 (으)로 설정
FIONBIO, *argp=0은 차단 모드로 설정하고, *argp는 0이 아니면 비차단 모드로 설정할 수 있습니다.그러나 윈도우즈 플랫폼은 한 socket에 대해 WSAAsyncSelect () 또는 WSAEventSelect () 함수를 호출한 후에 ioctlsocket () 함수를 비차단 모드로 설정하면 실패합니다. 먼저 WSAAsyncSelect () 를 호출해야 합니다. lEvent 매개 변수를 0으로 설정하거나 WSAEventSelect () 를 0으로 설정하여 각각 WSAAsyncSelect () 나 WSAEventSelect () 를 비활성화해야 합니다.이 소켓을 차단 모드로 설정하려면 ioctlsocket () 을 다시 호출해야 합니다.WSAAsyncSelect () 또는 WSAEventSelect () 함수를 호출하면 socket이 자동으로 비차단 모드로 설정되기 때문입니다.msdn의 원어는:
The WSAAsyncSelect and WSAEventSelect functions automatically set a socket to nonblocking mode. If WSAAsyncSelect or WSAEventSelect has been issued on a socket, then any attempt to use ioctlsocket to set the socket back to blocking mode will fail with WSAEINVAL.
To set the socket back to blocking mode, an application must first disable WSAAsyncSelect by calling WSAAsyncSelect with the lEvent parameter equal to zero, or disable WSAEventSelect by calling WSAEventSelect with the lNetworkEvents parameter equal to zero.
사이트 주소:https://msdn.microsoft.com/en-us/library/windows/desktop/ms738573(v=vs.85).aspx
4. 실제 프로젝트에서 이전 선배들이 남긴 코드를 보면 한 순환에서 fcntl() 또는 ioctlsocket() 함수를 호출하여 socket의 비차단 모드를 사용한다. 코드는 다음과 같다.
for (;;)
{
#ifdef UNIX
on=1;
if (ioctlsocket(id, FIONBIO, (char *)&on) < 0)
#endif
#ifdef WIN32
unsigned long on_windows=1;
if (ioctlsocket(id, FIONBIO, &on_windows) < 0)
#endif
#ifdef VOS
int off=0;
if (ioctlsocket(id, FIONBIO, (char *)&off) <0)
#endif
{
if (GET_LAST_SOCK_ERROR() == EINTR)
continue;
RAISE_RUNTIME_ERROR("Can not set FIONBIO for socket");
closesocket(id);
return NULL;
}
break;
}
이렇게 할 필요가 있는지 없는지는 고증할 필요가 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.