千家信息网

socket怎么设置为非阻塞模式

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,今天就跟大家聊聊有关socket怎么设置为非阻塞模式,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1. windows平台上无论利用socke
千家信息网最后更新 2025年01月23日socket怎么设置为非阻塞模式

今天就跟大家聊聊有关socket怎么设置为非阻塞模式,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

1. windows平台上无论利用socket()函数还是WSASocket()函数创建的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. 另外,windows和linux平台上accept()函数返回的socekt也是阻塞的,linux另外提供了一个accept4()函数,可以直接将返回的socket设置为非阻塞模式:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);     int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);

只要将accept4()最后一个参数flags设置成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标识,而不是要同时设定。

windows上可调用ioctlsocket函数:

int ioctlsocket(    _In_    SOCKET s,    _In_    long   cmd,    _Inout_ u_long *argp  );

将cmd参数设置为FIONBIO,*argp=0即设置成阻塞模式,而*argp非0即可设置成非阻塞模式。但是windows平台需要注意一个地方,如果你对一个socket调用了WSAAsyncSelect()或WSAEventSelect()函数后,你再调用ioctlsocket()函数将该socket设置为非阻塞模式,则会失败,你必须先调用WSAAsyncSelect()通过设置lEvent参数为0或调用WSAEventSelect()通过设置lNetworkEvents参数为0来分别禁用WSAAsyncSelect()或WSAEventSelect()。再次调用ioctlsocket()将该socket设置成阻塞模式才会成功。因为调用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;  }

看完上述内容,你们对socket怎么设置为非阻塞模式有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。

阻塞 函数 模式 参数 平台 内容 必要 代码 数据 文章 标志 标识 要么 成功 再次 前辈 原话 可以通过 同时 地方 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 国家图书馆俄文数据库 找不到可修改的申报数据库 池州咖啡点餐软件开发要多少钱 创建数据库指定路径 服务器电源用在台式机 合肥服务器工控机厂家 公安特殊专技(网络安全防护) 厦门bim软件开发工程 手机玩韩服需要服务器吗 农业银行软件开发离职率 霸州管理软件开发 服务器外接显示屏没有画面 数据库报-407 窝乐互联网信息科技有限公司 oa系统软件开发公司 数据库原理与技术视频 虹口区大型软件开发售后保障 连接运营商服务器时出错 金山区咨询软件开发包括什么 连接数据库的四大条件 软件开发内存多少最合适 工控网络安全哪家做得好 鱼泡网软件开发有几年 我的世界服务器每隔2小时重启 数码视讯网络安全龙头股 怎么判断数据库的主键是什么意思 服务器连接数据库mysql 侵犯网络安全法 数据库系统及应用崔巍 数据库中短整型什么意思
0