下面是接受客户端的代码......我刚添加了一些内容,将其添加到一个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();
答案 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()
。由于charB
是char*
而不是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;
}
}
...
}
...
}