【问题标题】:How does Winsock2 listen() blocks?Winsock2 listen() 是如何阻塞的?
【发布时间】:2013-05-14 18:10:04
【问题描述】:

MSDN 说: Listen() 是一个阻塞调用。我使用了 listen() 的函数的代码 sn-p 如下所示:

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 page 中也有明确的解释:

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

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

【问题讨论】:

  • 我注意到您复制的文档引用指的是Listen,而不是listen。也许它们是两种不同的功能?
  • @Celada :不。两者都是一样的

标签: linux windows sockets blocking winsock2


【解决方案1】:

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

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

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

【讨论】:

  • 是的,这可能是 MSDN 将那段放在此处的原因。谢谢大家。
【解决方案2】:

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

编辑0:

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

【讨论】:

  • 持有那个锁是为了什么冲突的目的?我将其称为“原子”调用而不是“阻塞”调用。
  • 是的,你可能是对的。它肯定不会在任何健全的操作系统上“阻塞”。但是Windows远非“理智”。不过会改变措辞,谢谢。
【解决方案3】:

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

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

【讨论】:

  • 我不知道……Windows Sockets SPI 似乎没有禁止第三方协议提供程序阻止 listen
  • 所以我们现在需要的只是一个关于他们可能会阻止它+on 的合理建议。+ 我不赞成您对 NIC 驱动程序的建议。 listen()目前与网络无关。
  • 我能想到一个稍微做作的例子:如果网络提供商透明地将套接字重定向到远程系统,它可能需要等待该远程系统响应。我不知道有任何现有的软件可以做这种事情,但它可能很有用;它将允许多台计算机共享一个 IP 地址,而不受 NAT 的限制。
  • 另外,虽然传统的 NIC 不需要被告知 listen 调用,但硬件卸载可能不会改变这一点吗?
猜你喜欢
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-15
  • 2021-04-17
  • 2012-11-13
相关资源
最近更新 更多