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

时间:2015-06-29 11:27:09

标签: 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;
}

1 个答案:

答案 0 :(得分:8)

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

listen function

  

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

     

说明:

     

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

accept function

  

accept函数允许套接字上的传入连接尝试。

     

说明:

     

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

     

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

相应的示例(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);
...