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()时没有阻塞,而是根据我的知识阻止接受,这是正确的方法。同样在Linux MAN page中,可以清楚地解释:
listen()将套接字fd引用的套接字标记为被动套接字,即作为套接字用于接受使用accept()的传入连接请求
那么为什么MSDN说listen是一个阻塞的Winsock调用。他们只是指任何内部等待某事件吗?
答案 0 :(得分:3)
所有文档都说明listen
可能阻止,而不是它肯定会阻止。它也可能只是非常短暂地阻塞,例如,等待NIC设备驱动程序完成现有活动。
Windows套接字允许安装第三方提供程序以支持其他协议或具有额外功能的现有协议。由于Winsock SPI不禁止第三方提供商阻止listen
,因此应用程序应遵循MSDN提供的有关APC和嵌套Winsock调用的建议。
内置的TCP / IP提供程序似乎永远不会阻塞listen
,但AFAIK没有明确的保证。
答案 1 :(得分:2)
在某种意义上,它可能是一个阻塞调用,操作系统可能需要确保调用线程具有对套接字的独占访问权限,这需要某种锁定,如果某些其他线程反过来可能会阻塞调用者认为锁定。
通常,对操作系统的任何调用都是用户空间线程被取消调度以支持其他更高优先级处理的机会。这通常不被称为“阻塞”,而是“睡觉”或被“抢先”。
答案 2 :(得分:1)
如果MSDN说,那就错了。这不是阻止电话。没有什么可以阻止的,当然也没有“外部网络事件”。
这样说的段落显然是模板复制到太多地方。