5

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()来使socket句柄阻塞类型。

输出是:通过听

因此,线程在listen() 处没有阻塞,而是在接受时阻塞,据我所知,这是正确的方法。在Linux MAN 页面中也清楚地解释了:

listen() 将 socket fd 引用的套接字标记为被动套接字,即将使用 accept() 接受传入连接请求的套接字

那为什么MSDN说listen是一个阻塞的Winsock调用。他们只是意味着任何内部等待某些事件吗?

4

3 回答 3

3

所有文档都说listen 可能会阻塞,而不是肯定会阻塞。它也可能只是非常短暂地阻塞,例如,等待 NIC 设备驱动程序完成现有活动。

Windows Sockets 允许安装第三方提供程序以支持附加协议或具有附加功能的现有协议。由于Winsock SPI不禁止第三方提供程序阻止listen,因此应用程序应遵循 MSDN 提供的关于 APC 和嵌套 Winsock 调用的建议。

似乎内置的 TCP/IP 提供程序永远不会阻塞,listen但 AFAIK 对此没有明确的保证。

于 2013-05-22T04:12:20.873 回答
2

从某种意义上说,它可能是一个阻塞调用,操作系统可能需要确保调用线程对套接字具有独占访问权,这需要某种锁,如果其他线程持有该锁,这反过来可能会阻塞调用者.

编辑0:

通常,对操作系统的任何调用都是取消调度用户线程以支持其他更高优先级处理的机会。这通常不称为“阻塞”,而是“休眠”或“被抢占”。

于 2013-05-21T12:16:52.543 回答
1

如果 MSDN 这么说,那就大错特错了。这不是阻塞呼叫。没有什么可以阻止的,当然没有“外部网络事件”。

这么说的段落显然是样板复制到太多地方。

于 2013-05-21T12:16:55.497 回答