(сокеты) функция accept отжирает 99% процессорного времени.

Тема в разделе "WASM.WIN32", создана пользователем ACF_muti1atoR, 9 май 2006.

  1. ACF_muti1atoR

    ACF_muti1atoR New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    30
    Адрес:
    Провода
    пытаюсь написать сервер рассчитанный на работу с несколькими клиентами одновременно.

    с сокетами разобрался. всё как бы ок работает, но! в простое сервер отжирает 99% процессорного времени!! а именно функция accept. Я не могу понять почему. причём это происходит при абсалютно любом приоритете потока в котором вызываеться accept.



    код потока ниже, который принимает подключения от клиентов. (придумал сам, так что выглядеть может несколько по ламерски).



    В 98 винде кстате такой ошибки я не замечал... а вот в ХР и 2000 такая фигня твориться. Эти тормоза мешают обработке подключения клиента. А в 98 винде всё работает зишибись. быстро и без глюков.



    Помогите пожалуйста если не сложно. Что мне сделать, что бы этих тормозов небыло ?
    Код (Text):
    1.  
    2. unsigned long WINAPI EstablishConnectionProc(void *Param_Socket)
    3. {
    4.   HANDLE         DummyEvent = CreateEvent(0, true, false, "EstCon");
    5.   SOCKET        *ConnectionSocket = (SOCKET*)Param_Socket;
    6.   SOCKET         TempSocket;
    7.   int            SocketError;
    8.   unsigned int   ClientNum = 0;
    9.  
    10.    SetThreadPriority(EstablishConnectionThread, THREAD_PRIORITY_NORMAL);
    11.  
    12.    /* initialising slots */
    13.    for (ClientNum=0; ClientNum<SW_MAX_CLIENTS; ClientNum++)
    14.    {
    15.       ClientSocket[ClientNum] = INVALID_SOCKET;
    16.    }
    17.  
    18.    while(true)
    19.    {
    20.       SocketError = listen(*ConnectionSocket, 1);
    21.  
    22.       if (SocketError == INVALID_SOCKET)
    23.       {
    24.          /* problems with connection socket */
    25.          MessageBox(NULL, "ServerEstablishThreadFailure", "", MB_OK); //temp
    26.          closesocket(*ConnectionSocket);
    27.          ExitThread(SW_THR_SELFKILLED);
    28.       }
    29.  
    30.       /* awaiting connections */
    31.       while (true)
    32.       {
    33.          /* accept new client if server have free slot */
    34.          for (ClientNum=0; ClientNum<SW_MAX_CLIENTS; ClientNum++)
    35.          {
    36.             if (ClientSocket[ClientNum] == INVALID_SOCKET)
    37.             {
    38.                while (ClientSocket[ClientNum] == INVALID_SOCKET)
    39.                {
    40.                   ClientSocket[ClientNum] = accept(*ConnectionSocket, NULL, NULL); // вот здесь каждый проход цикла функция отжирает 99%
    41.                }
    42.  
    43.                SvSockReadThread[ClientNum] = CreateThread(NULL, NULL, SvSockReadProc, (void*)&ClientNum, NULL, &SvSockReadThreadID[ClientNum]);
    44.  
    45.                if (SvSockReadThread == INVALID_HANDLE_VALUE)
    46.                {
    47.                   /* cannot create thread for new client */
    48.                   ClientSocket[ClientNum] = INVALID_SOCKET;
    49.                   WaitForSingleObject(DummyEvent, 1000);
    50.                   break; //returns to awaiting connections
    51.                }
    52.                else
    53.                {
    54.                   WaitForSingleObject(DummyEvent, 1000); //because ClientNum problem
    55.                   break; //returns to awaiting connections
    56.                }
    57.             }
    58.          }
    59.  
    60.          WaitForSingleObject(DummyEvent, 1000); //speed optimisation
    61.       }
    62.    }
    63. }
    64.  
     
  2. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    вообщето такого не замечал . С кодом твоим пока не разбирался (( извини нет времени. Но показать пример обработки соединений могу. На каждый accept создается поток, обрабатывающий соединение. Сделано буквально по минимуму.
     
  3. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
  4. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    а, по поводу твоего кода.. убрал я там 1 строчку - не грузится ничего. (установки приоритета - так как этого треда у меня нет)

    Может и не из за этой процедуры, которую ты привел, у тебя все грузилось

    В аттаче пример с твоей функцией. У меня проц не грузится при accept вызове.

    [​IMG] _1094411211__funct_test2.rar
     
  5. KiNDeR

    KiNDeR New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2003
    Сообщения:
    258
    Адрес:
    Russia
    А зачем тебе тройной цикл while??? можно и одним обойтись... см. аттач! или статью
     
  6. ACF_muti1atoR

    ACF_muti1atoR New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    30
    Адрес:
    Провода
    действительно. это у меня какие-то глюки. мне просто показалось что когда я функцию accept закомментировал, то тормоза прекратились. однако это был еденичный случай.

    тормозит вообще даже не этот поток. я его переписал (в один while сделал), а затем совсем убрал, но всё равно дикие тормоза.



    сейчас буду опять искать где. .
     
  7. ACF_muti1atoR

    ACF_muti1atoR New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    30
    Адрес:
    Провода
    всё нашел. почему-от .. по каким-то одному биллу гейтсу причинам тормоза выдавал вот этот вот поток


    Код (Text):
    1.  unsigned long WINAPI OutputProc(void *Param)
    2. {
    3.    SetThreadPriority(OutputProcThread, THREAD_PRIORITY_NORMAL);
    4.  
    5.    HANDLE   DummyEvent = CreateEvent(0, true, false, "SocRea");
    6.  
    7.    while(true)
    8.    {
    9.       if (strlen(CommonRecvBuff) != 0)
    10.       {
    11.          Form1->Memo2->Lines->Add("ïðèøëî " + IntToStr(strlen(CommonRecvBuff)));
    12.          EnterCriticalSection(CritSection1);
    13.             myOutput(CommonRecvBuff);
    14.          LeaveCriticalSection(CritSection1);
    15.       }
    16.       //WaitForSingleObject(DummyEvent, 100);
    17.    }
    18. }
    19.  
    20.  






    Но стоило мне расскоментировать Waitforsingleobject и написать ему ждать 100мс... как тормоза исчезли.



    я этого не понимаю.. потому что всю жизнь потоки и без WaitForSingleObject пахали отлично и ничего не грузили..



    видать это как-то связано с критической секцией. но я не думал, что вход и выход из неё могут ТАК загрузить проц
     
  8. Klajnor_666

    Klajnor_666 New Member

    Публикаций:
    0
    Регистрация:
    23 мар 2006
    Сообщения:
    22
    Адрес:
    Russia
    Скорее это связанно с

     
  9. ACF_muti1atoR

    ACF_muti1atoR New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    30
    Адрес:
    Провода
    дык на самом деле ваще ничего не понятно по одной простой причине: CommonRecvBuff у меня заполнен нулевыми байтами. т.е. условие никогда верное не будет. следовательно дело до Memo и до Критической секции не доходит..



    не может же strlen в бесконечном цикле занимать 99% процессорного времени 8)).
     
  10. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348




    почему нет? :)
     
  11. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    А вообще очень плохой код.. В цикле постоянно проверять длинну строки. А потом еще раз ее брать..



    Мой совет - в этом коде оставить только вывод в мемо и критическую секцию. А вызывать уже этот вывод либо по таймеру, либо установкой евента после удачного завершения функции recv (это будет лучше).
     
  12. ACF_muti1atoR

    ACF_muti1atoR New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    30
    Адрес:
    Провода




    шутишь что ли ?? 8)). это вообще отладочный код. нужен был только для проверки работы сервера. в проге такой ереси естественно не будет.
     
  13. DrSex

    DrSex Юрий

    Публикаций:
    0
    Регистрация:
    1 апр 2005
    Сообщения:
    98
    Адрес:
    Россия
    Народ!

    Проблемы то нет. Если поток OutputProc в бесконечном цикле чего-то делает, то ему и будет выдаваться очень много процессорного времени (особенности архитектуры мультитрединга). Напиши в этом цикле Sleep(5); и все будет ок. :)



    Кусок кода со 100% загрузкой:

    while(1){

    //work

    }



    Кусок кода без 100% загрузкой:

    while(1){

    //work

    Sleep(10);

    }



    У самого в сервере была такая же проблема. Написал строчку Sleep(10); и все. :)



    В твоем случае вместо Sleep выступает WaitForSingleObject(...,100).