[英]How does Winsock2 listen() blocks?
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()使其成為套接字句柄阻塞類型。
輸出為:Passed listen
因此,線程不是在listen()處阻塞,而是在接受時阻塞,據我所知,這是正確的方法。 同樣在Linux MAN頁面中也有明確說明:
listen()將套接字fd所引用的套接字標記為被動套接字,即,該套接字將用於使用accept()接受傳入的連接請求
那么,為什么MSDN說監聽是阻塞Winsock的調用。 它們只是意味着任何內部在等待某個事件嗎?
所有文檔說的是, listen
可能會阻止,但不一定會阻止。 它也可能只是非常短暫地阻塞,例如,等待NIC設備驅動程序完成現有活動。
Windows套接字允許安裝第三方提供程序以支持其他協議或具有其他功能的現有協議。 由於Winsock SPI並不禁止第三方提供商阻止listen
,因此應用程序應遵循MSDN提供的有關APC和嵌套Winsock調用的建議。
內置的TCP / IP提供程序似乎從不阻止listen
但AFAIK對此沒有明確的保證。
從某種意義上說,這可能是個阻塞調用,操作系統可能需要確保調用線程具有對套接字的獨占訪問權,這需要某種類型的鎖,如果其他某個線程持有該鎖,則反過來可能會阻塞調用者。 。
通常,對操作系統的任何調用都是為用戶域線程調度的機會,以支持其他更高優先級的處理。 但是,這通常不稱為“阻止”,而是“睡眠”或“被搶占”。
如果MSDN這樣說,那就錯了。 這不是阻塞電話。 沒有什么可以阻止的,當然也沒有“外部網絡事件”。
這樣說的段落顯然被復制到太多地方。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.