Ниже приведен код, который принимает клиента... Я просто добавил немного, чтобы добавить его в пул, который является 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();
Я вижу несколько проблем с вашим кодом.
Вы передаете ListenSocket
Client()
когда вам следует передавать ClientSocket
:
addClient2Pool(Client(ClientSocket, inet_ntoa(n.sin_addr)));
Если вам необходимо закрыть сервер по какой-либо причине, вы должны закрыть все активные клиентские сокеты. В вашем примере, если accept()
терпит неудачу, вы вызываете closesocket(ListenSocket)
и WSACleanup()
не очищая сначала mainClientPool
(я предполагаю, что ваш mainClientPool
~Client()
closesocket()
вызывает closesocket()
в клиентском сокете):
mainClientPool.clear(); // <-- add this
closesocket(ListenSocket);
WSACleanup();
Когда вы перебираете свой список, вам нужно использовать Client&
reference при отсрочке итератора, чтобы вы не делали временные копии объектов 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;
}
}
...
}
...
}