Winsock multi client и multi thread, компьютер усердно работает

0

Я пытаюсь создать сервер нескольких клиентов в программировании сокетов c++, и я нашел некоторые проблемы в нескольких потоках. Я использую _beginthread для создания некоторых потоков. когда мы хотим построить многосерверный сервер, я думаю, что мы должны иметь поток, который обрабатывает сокет accepter в любое время с циклом, и пока он работает нормально (без проблем на мне).

после этого я делаю некоторые потоки для обработки Client-DataReceiver, и я думаю, что это лучше, чем мы создаем 1 поток для обработки всех клиентов с циклом для всех клиентов поочередно. Я думаю, что несколько потоков будут работать лучше, поскольку они работают синхронно.

когда я закончил все это, сервер работает так медленно/сложно, и они даже используют до 100% использования процессора? и, возможно, там что-то не хватает/неправильно в моем коде?

   void Initialize(){
      [....Server initialize goes here...]
       _beginthread( acceptNewClient, 0, (void*)1);  //the thread that handle accepter
    }
    SOCKET ClientSocket;
    void acceptNewClient(void* arg)
{
    while(true){
    ClientSocket = accept(ListenSocket,NULL,NULL);
    if (ClientSocket != INVALID_SOCKET) 
    {
        char value = 1;
        setsockopt( ClientSocket, IPPROTO_TCP, TCP_NODELAY, &value, sizeof( value ) );
        Client_Socket *client = new Client_Socket(ClientSocket); 
        _beginthread(ReceiveFromClient, 1,client );   //handle of client data receiver
        client_list.push_back(client);
    }
  }     
}
void ReceiveFromClient(void* client_sockets)
{
   Client_Socket * client_socket = (Client_Socket*)client_sockets;
   while(true){
       server->doReceive();    
   }
}

Редактировать:

после выяснения этого случая, я думаю, что causer - это поток, который я даже попробовал в новом консольном проекте:

#include <process.h>
    void tes(void * arg){
        while(true){

        }
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    while(true){}
        return 0;
    }

поток слишком усерден для компьютера, и я думаю, что ошибка - это сам поток. этот код действительно делает CPU 100% CPU, есть ли что-то неправильное для моего кода потока или решения для решения этого случая?

  • 0
    Этот код немного запутанный и неполный ... Почему ClientReceiver() вызывает функцию сервера? Разве он не должен просто получать / отправлять, используя свой локальный сокет?
  • 0
    извините, если он неполон, но я пытаюсь прояснить это. ClientReceiver () все еще находится на сервере, они использовали для обслуживания клиентов. во-первых, на стороне сервера есть 2 класса: «класс сервера» - место, куда мы помещаем список сокетов клиентов, и второе: «служба дескриптора клиента», используемая для обработки сервиса с клиентского компьютера, например, для отправки данных с клиента на сервер, и получать данные от клиента к серверу.
Показать ещё 8 комментариев
Теги:
multithreading
sockets
winsock

3 ответа

2

Как я уже говорил несколько часов назад, причиной этого является то, что вы поместили свой сокет в неблокирующий режим по какой-то причине, и вы не используете select(), просто вращайте цикл вокруг recv(). Это не имеет никакого смысла, поскольку вы используете поток для каждого соединения.

Решение заключается не в том, чтобы перевести в режим блокировки в соответствии с вашим ответом, а в том, чтобы удалить код, который устанавливает режим неблокирования, в первую очередь, режим блокировки по умолчанию, как указано @cHao.

1

100% процессор, скорее всего, вызван while while (while(true) server->doReceive();). Правильный способ использования сокетов - дождаться сокета, пока не будет сделано что-то полезное. Стандартная функция C++, которая позволяет это select.

Более продвинутый подход будет заключаться в использовании портов завершения ввода-вывода, но на вашем этапе эта технология слишком продвинута и, возможно, даже не нужна.

  • 0
    я даже избавился от начального кода потока. и оставьте только 1 поток живым на Accepter Server. процессор сократился примерно до 50%. что-то не так с этим кодом? я запускаю этот поток в классе _beginthread (ReceiveFromClient, 1, client); _beginthread (acceptNewClient, 0, (void *) 1);
  • 1
    @Rizky Я не знаю, на какой код ты ссылаешься, но это не имеет значения. Переполнение стека предназначено не для вопросов «здесь что-то не так», а для вопросов «У меня есть такая-то проблема, когда я ожидаю одно, а испытываю другое». Опубликуйте другой вопрос, который явно относится ко второму типу, и кто-то должен вам помочь. Если вы хотите задать вопрос первого типа, перейдите в Code Review .
Показать ещё 3 комментария
0

я выяснил проблему. во-первых, если вы хотите создать сервер с потоком каждого клиента, первое, что нужно знать:

убедитесь, что вы предварительно установили режим блокировки в режим блокировки ioctlsocket

это на самом деле имеет смысл! ну, когда мы создавали поток вроде этого:

unsigned __stdcall threadFunc(void * arg) 
{   
    while(1) {

    }
    return 0;
}

выглядит таким простым кодом потока, но это было связано с тем, что cpu работает так сильно. когда функция recv winsocks вызывается с неблокирующим режимом, они всегда будут повторяться с инструкцией while, когда нет ничего более длинного для чтения, они вращаются так же быстро, как работает comp. конечно, это не очень хорошая идея. поэтому, если мы хотим его преодолеть, конечно, правильный способ: установить сокет на неблокируемый.

u_long iMode = 0;
iResult = ioctlsocket(ClientSocket, FIONBIO, &iMode);

когда recv() Socket, называемый машиной, будет ждать, пока не будет прочитано несколько байтов. таким образом, "быстрое формование" больше не будет

Спасибо, в любом случае..

  • 2
    Режим блокировки по умолчанию; вам не нужен дополнительный код для его установки. Если вы установили сокет как неблокирующий без уважительной причины, это была ваша ошибка.

Ещё вопросы

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