C++ 服务器端在listen() 上没有阻塞

Posted

技术标签:

【中文标题】C++ 服务器端在listen() 上没有阻塞【英文标题】:C++ server side not blocking on listen() 【发布时间】:2015-09-15 20:17:21 【问题描述】:

下面的代码不会阻塞在listen() 上,它只是完成了执行。你能告诉我为什么吗? (initWSA 返回 true,我检查了它)。我正在学习一个教程,但有人告诉我它应该阻止,因为它正在寻找连接的客户端。

#include <iostream>
#include <WinSock2.h>

#pragma comment(lib, "ws2_32.lib")
using namespace std;

#define PORT 10000
bool initWSA()
    WSADATA wsadata;
    int error = WSAStartup(0x0202, &wsadata);
    if (error) return false;
    if (wsadata.wVersion != 0x0202)
        WSACleanup();
        return false;
    
    return true;

void closeConnection(SOCKET s)

    //Close the socket if it exists
    if (s)
        closesocket(s);

    WSACleanup(); //Clean up Winsock

int main()
    initWSA();
    SOCKET s;
    SOCKADDR_IN addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s == INVALID_SOCKET) cout << "INVALID SOCKET" << endl;
    if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)
    cout << "SOCKET ERROR" << endl;
    
    listen(s, SOMAXCONN);
    //cout << "CAUGHT ONE" << endl;
    //closeConnection(s);
    return 0;

【问题讨论】:

listen() 是非阻塞的。 accept() 阻塞并在连接时返回一个客户端服务器套接字。 那听什么? Err.. man listen, or Google 'listen()' 那么我应该先调用listen然后在它之后接受吗?编辑:是的,它有效,谢谢,你可以发布答案:) listen() 告诉操作系统开始将connect() 的潜在客户端排队到您的服务器(并提示允许多少挂起的连接)...accept() 实际上使对等方对等连接。你确实应该accept() 【参考方案1】:

首先,让我们澄清listen()accept() 函数的确切语义。

listen function:

listen 函数将套接字置于侦听传入连接的状态。

备注:

为了接受连接,首先使用 socket 函数创建一个套接字,并使用 bind 函数绑定到本地地址。 listen 指定传入连接的积压,然后使用 accept 函数接受连接。面向连接的套接字,例如 SOCK_STREAM 类型的套接字,与 listen 一起使用。套接字 s 被置于被动模式,其中传入的连接请求被确认并排队等待进程接受。

accept function:

accept 函数允许对套接字进行传入连接尝试。

备注:

accept 函数提取套接字 s 上未决连接队列中的第一个连接。然后它创建并返回一个新套接字的句柄。新创建的套接字是处理实际连接的套接字;它具有与 socket 相同的属性,包括使用 WSAAsyncSelectWSAEventSelect 函数注册的异步事件。

如果队列中没有挂起的连接,accept 函数可以阻塞调用者直到连接存在,并且套接字被标记为阻塞。如果套接字被标记为非阻塞并且队列中没有挂起的连接,accept 将返回如下所述的错误。 accept成功完成后返回一个新的socket句柄,接受的socket不能用于接受更多的连接。原始套接字保持打开状态并侦听新的连接请求。

适当的例子(source):

...
//----------------------
// Listen for incoming connection requests.
// on the created socket
if (listen(ListenSocket, 1) == SOCKET_ERROR) 
    wprintf(L"listen failed with error: %ld\n", WSAGetLastError());
    closesocket(ListenSocket);
    WSACleanup();
    return 1;

//----------------------
// Create a SOCKET for accepting incoming requests.
SOCKET AcceptSocket;
wprintf(L"Waiting for client to connect...\n");

//----------------------
// Accept the connection.
AcceptSocket = accept(ListenSocket, NULL, NULL);
if (AcceptSocket == INVALID_SOCKET) 
    wprintf(L"accept failed with error: %ld\n", WSAGetLastError());
    closesocket(ListenSocket);
    WSACleanup();
    return 1;
 else
    wprintf(L"Client connected.\n");

// No longer need server socket
closesocket(ListenSocket);
...

【讨论】:

感谢您的详尽回答。

以上是关于C++ 服务器端在listen() 上没有阻塞的主要内容,如果未能解决你的问题,请参考以下文章

tcp和udp

socket api- c/s模式:服务写,客户读. IO模式:阻塞

确定TCP listen()队列中当前的积压连接数

Linux之C++ socket通信编程

JAVA中Sockets长连接时使用read()阻塞的问题!急救!

非阻塞 Websockets C++ 奇怪的延迟