C++ 服务器端不阻塞 listen()

标签 c++ sockets connection server winsock

下面的代码不会阻塞在 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() 函数的确切语义。

listen function :

The listen function places a socket in a state in which it is listening for an incoming connection.

Remarks:

To accept connections, a socket is first created with the socket function and bound to a local address with the bind function. A backlog for incoming connections is specified with listen, and then the connections are accepted with the accept function. Sockets that are connection oriented, those of type SOCK_STREAM for example, are used with listen. The socket s is put into passive mode where incoming connection requests are acknowledged and queued pending acceptance by the process.

accept function :

The accept function permits an incoming connection attempt on a socket.

Remarks:

The accept function extracts the first connection on the queue of pending connections on socket s. It then creates and returns a handle to the new socket. The newly created socket is the socket that will handle the actual connection; it has the same properties as socket s, including the asynchronous events registered with the WSAAsyncSelect or WSAEventSelect functions.

The accept function can block the caller until a connection is present if no pending connections are present on the queue, and the socket is marked as blocking. If the socket is marked as nonblocking and no pending connections are present on the queue, accept returns an error as described in the following. After the successful completion of accept returns a new socket handle, the accepted socket cannot be used to accept more connections. The original socket remains open and listens for new connection requests.

适当的例子(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(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31114477/

相关文章:

c++ - 递归 std::functional 与递归匿名命名空间函数。使用哪一个?

c++ - 需要澄清 'reverse (data, data+n)' 在这段代码中做了什么

C++从文件中读取整数并保存到数组中

c++ - 停止并等待文件传输协议(protocol),什么时候停止监听?

Java 无法从 URL 获取请求的文件

c - recvfrom() 总是返回零远程地址

mysql - 来自 django 应用程序的每个请求都会增加 mysql 连接数

c++ - 无法将 insert() 结构插入 unordered_set

ios - 在 iOS 9 中检查互联网连接失败?

php - MySQL 连接不工作 : 2002 No such file or directory