C ++ Custom Client Handler

0

Ниже приведен код, который принимает клиента... Я просто добавил немного, чтобы добавить его в пул, который является 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();

Теги:
sockets
winsock

1 ответ

0
Лучший ответ

Я вижу несколько проблем с вашим кодом.

Вы передаете 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;
            }
        }
        ...
    }
    ...
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню