C ++自定义客户端处理程序

时间:2014-12-04 21:17:53

标签: c++ sockets winsock

下面是接受客户端的代码......我刚添加了一些内容,将其添加到一个list<Client>的池中。 Client是我自己的类,由(SOCKET, Char*)套接字和IP地址定义。 addclient2pool()函数只会添加到列表中。然后我遍历列表并通过Client中存储的套接字发送数据。

while(true) { 
    ClientSocket = accept(ListenSocket, (struct sockaddr *) &n, &len);
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return;
    }
    addClient2Pool(Client(ListenSocket, inet_ntoa(n.sin_addr)));
}

套接字似乎已关闭,因此我无法发送消息... 10057。我很确定我将套接字存储到Client类的方式存在根本性的错误,但我是C ++的新手。

void messageHandler() {
    int iSend;
    char* charB = "hello!";
    while(true) { 
        for(ClientPool::iterator it = mainClientPool.begin(); it != mainClientPool.end(); ++it) {
            Client c = *it;
            SOCKET sock = c.getSocket(); 
            iSend = send(sock, charB, sizeof(charB),0);
            if (iSend == SOCKET_ERROR) {
                printf("send failed with error: %d\n", WSAGetLastError());
            }
        }
        Sleep(2000);
    }
}

我使用了std::thread nameofthread(void)nameofthread.join();

1 个答案:

答案 0 :(得分:0)

我发现您的代码存在一些问题。

当您应该通过ListenSocket时,您正在将Client()传递给ClientSocket

addClient2Pool(Client(ClientSocket, inet_ntoa(n.sin_addr)));

如果您因任何原因需要关闭服务器,则应首先关闭所有活动的客户端套接字。在您的示例中,如果accept()失败,您首先调用closesocket(ListenSocket)WSACleanup()而不先清除mainClientPool(我假设您的~Client()解构函数调用closesocket()在客户端套接字上):

mainClientPool.clear(); // <-- add this
closesocket(ListenSocket);
WSACleanup();

循环遍历列表时,需要在引用迭代器时使用Client&引用,这样就不会对Client对象进行临时副本,这些对象在超出范围时会调用它们的析构函数(从而关闭客户端套接字):

Client &c = *it; // <-- add '&'

您滥用sizeof()。由于charBchar*而不是char[],因此您需要使用strlen()代替:

iSend = send(sock, charB, strlen(charB), 0);

最后,当send()(或任何其他套接字操作)失败时,您应关闭发生故障的客户端套接字并将其从列表中删除。这意味着将for()循环更改为while()循环,以便在循环播放时修改列表:

void messageHandler() {
    ...
    while(true) { 
        ...
        ClientPool::iterator it = mainClientPool.begin();
        while (it != mainClientPool.end()) {
            ...
            if (iSend == SOCKET_ERROR) {
                ...
                it = mainClientPool.erase(it);
            } else {
                ++it;
            }
        }
        ...
    }
    ...
}
相关问题