Потоки.Как сделать по оптимальней.

Тема в разделе "WASM.BEGINNERS", создана пользователем _nic, 22 фев 2009.

  1. _nic

    _nic New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2007
    Сообщения:
    372
    Код (Text):
    1. #include <stdio.h>
    2. #include <windows.h>
    3. #include <winsock2.h>
    4. char *list=new char[1024*1024];
    5. struct datas
    6. {
    7. SOCKET ss;
    8. SOCKADDR_IN sadr;
    9. };
    10. DWORD WINAPI admin(LPVOID lParam)
    11. {
    12. char *buf=new char[1024];
    13. SOCKET sin,sout;SOCKADDR_IN ladr,cadr;
    14. //WSADATA wsd;
    15. //WSAStartup(MAKEWORD(2,0),&wsd);
    16. ladr.sin_family=AF_INET;
    17. ladr.sin_port=htons(260);
    18. ladr.sin_addr.s_addr=0;
    19. sin=socket(AF_INET,SOCK_STREAM,0);
    20. bind(sin,(sockaddr*)&ladr,sizeof(ladr));
    21. listen(sin,1);
    22. int sz=sizeof(cadr);
    23. sout=accept(sin,(sockaddr*)&cadr,&sz);
    24. //что тут нужно делать?
    25. }
    26. DWORD WINAPI twins(LPVOID lParam)
    27. {
    28. datas *params=(datas*)lParam;
    29. SOCKET s;s=params->ss;
    30. char *buf=new char[1024];
    31. for(;;)
    32. {
    33. recv(s,buf,1024,0);
    34. Sleep(500);
    35. send(s,buf,strlen(buf),0);
    36. if(strcmp(buf,"exit")==0){break;}
    37. memset(buf,NULL,strlen(buf));
    38. }
    39. delete []buf;
    40. }
    41. int main()
    42. {
    43. char ip[16];
    44. DWORD id,id_a;
    45. SOCKET sin,sout;WSADATA wsd;
    46. SOCKADDR_IN ladr,cadr;
    47. datas params;
    48. WSAStartup(MAKEWORD(2,0),&wsd);
    49. ladr.sin_family=AF_INET;
    50. ladr.sin_port=htons(250);
    51. ladr.sin_addr.s_addr=0;
    52. sin=socket(AF_INET,SOCK_STREAM,0);
    53. bind(sin,(sockaddr*)&ladr,sizeof(ladr));
    54. CreateThread(0,0,&admin,0,0,&id_a);
    55. for(;;)
    56. {
    57. Sleep(300);
    58. listen(sin,10);
    59. int sz=sizeof(cadr);
    60. sout=accept(sin,(sockaddr*)&cadr,&sz);
    61. params.ss=sout;
    62. params.sadr=cadr;
    63. getpeername(sout,(sockaddr*)&cadr,&sz);
    64. wsprintf(ip,"%s",inet_ntoa(((SOCKADDR_IN *)&cadr)->sin_addr));
    65. if(strstr(ip,list)==NULL)
    66. {
    67. strcat(list,ip);strcat(list,"\n");
    68. CreateThread(0,0,&twins,(void*)&params,0,&id);
    69. }
    70. }
    71. //WSACleanup();
    72. }
    Вопрос в том как по элегантней управлять потоками стартующими при подключение на 250 порт.Тоесть надо что бы был активен лиш один поток.То есть при их старте они должны как бы спать пока через "админский" поток будет выбран поток с нужным айпи клиента,и тогда поток с нужным айпи должен "просыпатся".Мне не приходит в голову ничего кроме как чекать в бесконечном цикле со Sleep из всех запущенных потоков глобальную переменную на предмет наличия в ней нужного айпи :dntknw: Но хотелось бы найти такое решение при котором нагрузка на процессор будет как можно меньше.Подскажите пожалуйста альтернативный подход.
     
  2. Dian

    Dian Member

    Публикаций:
    0
    Регистрация:
    19 июн 2008
    Сообщения:
    222
    По идее это можно вообще перепоручить системе:
    http://www.rsdn.ru/article/baseserv/threadpool.xml
     
  3. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    Я тоже за тред пул.
     
  4. Aspire

    Aspire New Member

    Публикаций:
    0
    Регистрация:
    19 май 2007
    Сообщения:
    1.028
    Partner Тут че, голосование? Тогда я - за порты завершения и перекрытый ввод/вывод.
     
  5. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    Aspire
    Да, проголосуем и заставим автора сделать как решило большинство ;)
     
  6. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    _nic, в сердце нормального сервера всегда есть event demultiplexor и один поток обслуживает несколько соединений. Самый простой подход это select(). Попробуй сначала с одним потоком и blocking sockets, потом добавь ещё worker threads.

    Когда освоишь, переходи на overlapped IO и IO Completion ports. Идея та же - один поток обслуживает несколько соединений, у тебя несколько потоков, но все сетевые операции выполняются асинхронно.
     
  7. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    +1s0larian я тут предлагал такое написать ручками, но Aspire'у это почему-то не понравилось
     
  8. Aspire

    Aspire New Member

    Публикаций:
    0
    Регистрация:
    19 май 2007
    Сообщения:
    1.028
    max7C4 Ыыы
    Что вы предлогали нопесать ручкоме? И что мне не понравилось?
    По памяти... у нас с Вами спор был завязан на необходимости использования ioctlsocket, всего лишь.
    Кроме того, если уж переносить спор в эту тему, то Ваш супер-мега-сервер, на сколько я понял, написан на блокирующих сокетах. Ни слова не слышал про select, а уж про IOCP ваще речи не идет. ТС спросил "как пооптимальней?".
    Мое мнение, что пул потоков (клиент = поток) - не оптимально.
    Блокирующие сокеты - не оптимально.
    Более оптимально: много клиентов + несколько потоков + юзаем select.
    Еще более оптимально: много клиентов + несколько потоков + юзаем IOCP.

    И спорить тут особо неочем. Все это давно написано, разжевано и в рот положено.
     
  9. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    Это факт - такой код не тянет 1000 одновременных соединений на Windows и средней машине.

    Тоже факт - N потоков тянут только N медленных клиентов в случае отправки большого кол-во данных.

    Тут просто компромис - сложность реализации против производительности (scalability).
     
  10. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    s0larian
    Пул потоков это не (клиент = поток), а некоторое фиксированое количество потоков. Если клиентов больше чем потоков, то запросы от клиентов ставятся в очередь и ждут свободного потока.
     
  11. _nic

    _nic New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2007
    Сообщения:
    372
    В моем случае постановка задачи такова.Что обмен данными должен идти только с одним клиентом.Все остальные должны быть как бы "замороженны" до поры до времени.
     
  12. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Aspire
    Если Вы не поняли, то select и memory manager реализованы в моем случае ручками. И работает все превосходно. Я ни слова не сказал про блокирующие т.к. работает не только с ними.
     
  13. Aspire

    Aspire New Member

    Публикаций:
    0
    Регистрация:
    19 май 2007
    Сообщения:
    1.028
    max7C4 @ля, убейтесь ап стену со своим select'ом реализованным ручками через ioctlsocket - читай - "через *опу".
     
  14. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    не через ioctlsocket. это лишь метод управления памятью. (дабы не разбрасываться мегабайтами, мелочно)
     
  15. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    Это ты к чему мне объясняешь?
     
  16. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    То есть poll (тупо критим цикл и ждём пока придут данные)? Или через events? Если второе, то это просто замена select() на WaitForMultipleObjects(). На этот вызов, кста, принемает не больше 32 объектов и след-но надо писать ещё тупой код для проверки блоков из 32-х объектов...

    Кста, о каких "разбросанных мегабайтах" речь? Что-то ты не то оптимизируешь...
     
  17. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    тут все более хитро. не для языков высокого уровня. есть область памяти, где будут размещаться обработчики объектов, но их цель лишь установить пометку объекту. обработчики генерируются динамически при создание объекта. каждый обработчик это код, который вызывается при срабатывание того или иного event'а, и выбирающего из таблицы (читай синхронный, между потоками, список) его указатель на структуру, а после вызывающей функцию, которую я уже приводил. что бы в слепую не выделять память перед получением данных. менеджер памяти использует мои алгоритмы работы с памятью и они обгоняют виндовые, но разбрасываться мегабайтами я не могу, т.к. придется расширять буфер и делать его составным. это предусмотрено, но крайне не желательно. поэтому я предпочитаю немного посчитать и выделить буфер требуемого объема, который будет рационально загружен (и не будет переполняться) при пиковой загрузке сети. этот сервер уже проверялся и успешно функционирует, выжимая из гигабитного канала максимум производительности.
    upd: цифры смотри в предыдущей теме. суть в том, что код для каждого клиента получается линеен и не требует сложных алгоритмов поисков.
     
  18. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    max7C4, так ёлки, как ты ожидаешь прихода данных?

    Твой код тянет сотни одновременных клиентов? Ты это тестировал? Как насчёт нескольких сотен клиентов льющик на 28kbps?
     
  19. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    до 5000 клиентов на скорости до 200 kbps. загрузка iP4HT 35-40% в зависимости от данных для обработки. и это до сих пор работает
     
  20. Aspire

    Aspire New Member

    Публикаций:
    0
    Регистрация:
    19 май 2007
    Сообщения:
    1.028
    Это бесполезно )) Чувака заклинило. Он уже в стопицотый раз рассказывает про то, о чем его не спрашивают.
    Если повторить вопрос, то он обижается и бьет себя пяткой в грудь, заявляя, что уже 7.5 лет программирует на ассемблере. Сходу заявляет, что все его метОды "не для языков высокого уровня", о которых он вам не расскажет потому, что вы все равно ничего не поймете, т.к. ассемблера тут кроме него никто не знает.