服务器编程心得(四)—— 如何将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, ) | O_NONBLOCK); ioctl(sockfd, FIONBIO, ); //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=;
if (ioctlsocket(id, FIONBIO, (char *)&on) < )
#endif #ifdef WIN32
unsigned long on_windows=;
if (ioctlsocket(id, FIONBIO, &on_windows) < )
#endif #ifdef VOS
int off=;
if (ioctlsocket(id, FIONBIO, (char *)&off) <)
#endif
{
if (GET_LAST_SOCK_ERROR() == EINTR)
continue;
RAISE_RUNTIME_ERROR("Can not set FIONBIO for socket");
closesocket(id);
return NULL;
}
break;
}
是否有必要这样做,有待考证。

服务器编程心得(四)—— 如何将socket设置为非阻塞模式的更多相关文章
- socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto
socket异步通信-如何设置成非阻塞模式.非阻塞模式下判断connect成功(失败).判断recv/recvfrom成功(失败).判断send/sendto 博客分类: Linux Socket s ...
- socket设置为非阻塞方式(windows和linux)
Windows用以下方法将socket设置为非阻塞方式 : unsigned long ul=1; SOCKET s=socket(AF_INET,SOCK_STREAM,0); int ret=io ...
- Socket 阻塞模式和非阻塞模式
阻塞I/O模型: 简介:进程会一直阻塞,直到数据拷贝 完成 应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好. 如果数据没有准备好,一直等待….数据准备好了,从内核拷贝到用户空间,IO函数返 ...
- UDP socket 设置为的非阻塞模式
UDP socket 设置为的非阻塞模式 Len = recvfrom(SocketFD, szRecvBuf, sizeof(szRecvBuf), MSG_DONTWAIT, (struct so ...
- 看到关于socket非阻塞模式设置方式记录一下。
关于socket的阻塞与非阻塞模式以及它们之间的优缺点,这已经没什么可言的:我打个很简单的比方,如果你调用socket send函数时: 如果是阻塞模式下: send先比较待发送数据的长度len和套接 ...
- NIO Socket非阻塞模式
NIO主要原理和适用 NIO 有一个主要的类Selector,这个类似一个观察者,只要我们把需要探知的socketchannel告诉Selector,我们接着做别的事情,当有 事件发生时,他会通知我们 ...
- Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO
Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO Java 非阻塞 IO 和异步 IO 转自https://www.javadoop.com/post/nio-and-aio 本系 ...
- Socket阻塞模式和非阻塞模式的区别
简单点说: 阻塞就是干不完不准回来, 非组赛就是你先干,我现看看有其他事没有,完了告诉我一声 我们拿最常用的send和recv两个函数来说吧... 比如你调用send函数发送一定的Byte,在系 ...
- 使用命名管道的OVERLAPPED方式实现非阻塞模式编程 .
命令管道是进程间通讯的一种常用方式,对于命令管道的介绍可以参考别的资料和书籍,这里推荐一个<VC++下命名管道编程的原理及实现>这篇博文,写得比较清楚.但是都是介绍了阻塞模式的编程,我这里 ...
随机推荐
- (水题)洛谷 - P1003 - 铺地毯
https://www.luogu.org/problemnew/show/P1003 一开始觉得是用树套树来区间修改单点查询,但是发现空间不够开. 看了题解发现这个是静态的问题,而且只问一个点的结果 ...
- 51nod 1489 蜥蜴和地下室(dp)
传送门 题意 分析 dp[12][20][20][20]; // dp[a][b][c][d]第a个弓箭手面临第a-1.a.a+1个弓箭手的生命值分别为b.c.d的状态 转移巧妙,需注意 trick ...
- K8S学习心得 == kube-controller-manager 报错configmaps "extension-apiserver-authentication" is forbidden: User "kubernetes" cannot get resource "configmaps" in API group ""
当我按照教材设置证书,配置好kube-controller的相关条件后,启动kube-controller-manage组件,却意外报错. 一.基本信息如下: 1. kube-controller-m ...
- Luogu P1736 创意吃鱼法【dp】By cellur925
题目传送门 题意:给出一个01矩阵,找出一条对角线,使得对角线上的元素都为1,而对角线所在矩阵其他元素均为0,使得这样的对角线最长. 状态:$f[i][j]$表示以($i$,$j$)为对角线端点的最长 ...
- android 多线程 AsyncTask 下载图片
AsyncTask 下载图片 package com.test.network; import android.graphics.Bitmap; import android.graphics.Bit ...
- [NOIP2018校模拟赛]T1 阶乘
题目: 描述 有n个正整数a[i],设它们乘积为p,你可以给p乘上一个正整数q,使p*q刚好为正整数m的阶乘,求m的最小值. 输入 共两行. 第一行一个正整数n. 第二行n个正整数a[i]. 输出 共 ...
- 根据 目录号 案卷号 用户名 查询 page 中 的条数
select count(*) from am_b_page a join am_b_entry b on a.entry_id=b.entry_id where b.catalogue_code=' ...
- springboot 配置Ehcache
Ehcache的基本配置说明我就不说了.小编记录一下在springboot中使用Ehcache的使用方法. 第一步:在classpath下引入配置文件ehcache.xml 代码如下: <ehc ...
- 关于margin、padding 对内联元素的影响
内联元素和块级元素的区别是新手必须要掌握的知识点.大家可能平时注意块级元素比较多.所以这里重点让我们来讲讲常见的width height margin padding 对inline元素的影响. 测 ...
- mysql索引命中规则
转于:https://blog.csdn.net/claram/article/details/77574600 首先明确:为什么要用联合索引? 对于查询语句“SELECT E.* FROM E WH ...