MSDN说: Listen()是一个阻塞调用。下面显示了我在其中使用了listen()函数的代码片段:
sockaddr_in addr = {0};
int addrlen = sizeof(addr);
SOCKET sock_listen;
if(-1 == (sock_listen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)))
{
cout<<"error";
}
addr.sin_family = AF_INET;
/* Network byte ordered address for loopback */
addr.sin_addr.s_addr= inet_addr("127.0.0.1");
/* Let service provider assign a unique port from dynamic client port range */
addr.sin_port = 0;
if(-1 == bind(sock_listen, (const sockaddr *)&addr, addrlen))
{
CloseHandle((HANDLE)sock_listen_fd);
cout<<"error";
}
if(-1 == getsockname(sock_listen, (sockaddr *)&addr, &addrlen))
{
CloseHandle((HANDLE)sock_listen);
cout<<"error";
}
u_long mode = 0;
if(SOCKET_ERROR == ioctlsocket(sock_listen, FIONBIO, &mode))
{
cout<<"ioctl failed";
}
if(SOCKET_ERROR == listen(sock_listen, 1))
{
cout<<"listen error";
}
cout<<"Passed listen";
if(SOCKET_ERROR == (s = ACL_accept(sock_listen_fd, NULL, NULL)))
{
cout<<"accept error";
}默认情况下,作为阻塞类型创建的套接字句柄。为了进一步确保它调用ioctlsocket()来使套接字句柄阻塞类型。
输出是:传递侦听
因此,线程并没有阻塞listen(),而是阻塞了accept,据我所知,这是正确的方法。在Linux手册页中也有明确的解释:
侦听()将套接字fd所引用的套接字标记为被动套接字,即为将使用accept()接受传入连接请求的套接字。
那么,为什么MSDN说侦听是阻塞的Winsock调用。他们是说内部在等什么事吗?
发布于 2013-05-22 04:12:20
所有的文档都说listen可能会阻塞,而不是说它肯定会阻塞。它也可能只是非常短暂地阻塞,例如,等待NIC设备驱动程序完成现有活动。
Windows套接字允许安装第三方提供程序,以支持附加协议或具有额外功能的现有协议。由于温索克SPI不禁止第三方提供商阻止listen,所以应用程序应该遵循MSDN提供的关于APC和嵌套Winsock调用的建议。
似乎内置的TCP/IP提供程序从来不会阻止listen,但是AFAIK没有明确的保证。
发布于 2013-05-21 12:16:52
在某种意义上,这可能是一个阻塞调用,因为操作系统可能需要确保调用线程具有对套接字的独占访问权,而套接字需要某种类型的锁,如果其他线程持有该锁,则可能会阻塞调用方。
编辑0:
一般来说,对操作系统的任何调用都是用户线程被取消调度的机会,从而有利于其他更高优先级的处理。这通常不是所谓的“阻塞”,而是“睡眠”或“先发制人”。
发布于 2013-05-21 12:16:55
如果MSDN这么说,那就错了。这不是阻拦电话。没有什么可以阻止的,当然也没有“外部网络事件”。
这么说的段落显然是抄袭到太多地方的样板。
https://stackoverflow.com/questions/16645215
复制相似问题