Код (Text): #include <stdio.h> #include <windows.h> #include <winsock2.h> char *list=new char[1024*1024]; struct datas { SOCKET ss; SOCKADDR_IN sadr; }; DWORD WINAPI admin(LPVOID lParam) { char *buf=new char[1024]; SOCKET sin,sout;SOCKADDR_IN ladr,cadr; //WSADATA wsd; //WSAStartup(MAKEWORD(2,0),&wsd); ladr.sin_family=AF_INET; ladr.sin_port=htons(260); ladr.sin_addr.s_addr=0; sin=socket(AF_INET,SOCK_STREAM,0); bind(sin,(sockaddr*)&ladr,sizeof(ladr)); listen(sin,1); int sz=sizeof(cadr); sout=accept(sin,(sockaddr*)&cadr,&sz); //что тут нужно делать? } DWORD WINAPI twins(LPVOID lParam) { datas *params=(datas*)lParam; SOCKET s;s=params->ss; char *buf=new char[1024]; for(;;) { recv(s,buf,1024,0); Sleep(500); send(s,buf,strlen(buf),0); if(strcmp(buf,"exit")==0){break;} memset(buf,NULL,strlen(buf)); } delete []buf; } int main() { char ip[16]; DWORD id,id_a; SOCKET sin,sout;WSADATA wsd; SOCKADDR_IN ladr,cadr; datas params; WSAStartup(MAKEWORD(2,0),&wsd); ladr.sin_family=AF_INET; ladr.sin_port=htons(250); ladr.sin_addr.s_addr=0; sin=socket(AF_INET,SOCK_STREAM,0); bind(sin,(sockaddr*)&ladr,sizeof(ladr)); CreateThread(0,0,&admin,0,0,&id_a); for(;;) { Sleep(300); listen(sin,10); int sz=sizeof(cadr); sout=accept(sin,(sockaddr*)&cadr,&sz); params.ss=sout; params.sadr=cadr; getpeername(sout,(sockaddr*)&cadr,&sz); wsprintf(ip,"%s",inet_ntoa(((SOCKADDR_IN *)&cadr)->sin_addr)); if(strstr(ip,list)==NULL) { strcat(list,ip);strcat(list,"\n"); CreateThread(0,0,&twins,(void*)¶ms,0,&id); } } //WSACleanup(); } Вопрос в том как по элегантней управлять потоками стартующими при подключение на 250 порт.Тоесть надо что бы был активен лиш один поток.То есть при их старте они должны как бы спать пока через "админский" поток будет выбран поток с нужным айпи клиента,и тогда поток с нужным айпи должен "просыпатся".Мне не приходит в голову ничего кроме как чекать в бесконечном цикле со Sleep из всех запущенных потоков глобальную переменную на предмет наличия в ней нужного айпи Но хотелось бы найти такое решение при котором нагрузка на процессор будет как можно меньше.Подскажите пожалуйста альтернативный подход.
_nic, в сердце нормального сервера всегда есть event demultiplexor и один поток обслуживает несколько соединений. Самый простой подход это select(). Попробуй сначала с одним потоком и blocking sockets, потом добавь ещё worker threads. Когда освоишь, переходи на overlapped IO и IO Completion ports. Идея та же - один поток обслуживает несколько соединений, у тебя несколько потоков, но все сетевые операции выполняются асинхронно.
max7C4 Ыыы Что вы предлогали нопесать ручкоме? И что мне не понравилось? По памяти... у нас с Вами спор был завязан на необходимости использования ioctlsocket, всего лишь. Кроме того, если уж переносить спор в эту тему, то Ваш супер-мега-сервер, на сколько я понял, написан на блокирующих сокетах. Ни слова не слышал про select, а уж про IOCP ваще речи не идет. ТС спросил "как пооптимальней?". Мое мнение, что пул потоков (клиент = поток) - не оптимально. Блокирующие сокеты - не оптимально. Более оптимально: много клиентов + несколько потоков + юзаем select. Еще более оптимально: много клиентов + несколько потоков + юзаем IOCP. И спорить тут особо неочем. Все это давно написано, разжевано и в рот положено.
Это факт - такой код не тянет 1000 одновременных соединений на Windows и средней машине. Тоже факт - N потоков тянут только N медленных клиентов в случае отправки большого кол-во данных. Тут просто компромис - сложность реализации против производительности (scalability).
s0larian Пул потоков это не (клиент = поток), а некоторое фиксированое количество потоков. Если клиентов больше чем потоков, то запросы от клиентов ставятся в очередь и ждут свободного потока.
В моем случае постановка задачи такова.Что обмен данными должен идти только с одним клиентом.Все остальные должны быть как бы "замороженны" до поры до времени.
Aspire Если Вы не поняли, то select и memory manager реализованы в моем случае ручками. И работает все превосходно. Я ни слова не сказал про блокирующие т.к. работает не только с ними.
max7C4 @ля, убейтесь ап стену со своим select'ом реализованным ручками через ioctlsocket - читай - "через *опу".
не через ioctlsocket. это лишь метод управления памятью. (дабы не разбрасываться мегабайтами, мелочно)
То есть poll (тупо критим цикл и ждём пока придут данные)? Или через events? Если второе, то это просто замена select() на WaitForMultipleObjects(). На этот вызов, кста, принемает не больше 32 объектов и след-но надо писать ещё тупой код для проверки блоков из 32-х объектов... Кста, о каких "разбросанных мегабайтах" речь? Что-то ты не то оптимизируешь...
тут все более хитро. не для языков высокого уровня. есть область памяти, где будут размещаться обработчики объектов, но их цель лишь установить пометку объекту. обработчики генерируются динамически при создание объекта. каждый обработчик это код, который вызывается при срабатывание того или иного event'а, и выбирающего из таблицы (читай синхронный, между потоками, список) его указатель на структуру, а после вызывающей функцию, которую я уже приводил. что бы в слепую не выделять память перед получением данных. менеджер памяти использует мои алгоритмы работы с памятью и они обгоняют виндовые, но разбрасываться мегабайтами я не могу, т.к. придется расширять буфер и делать его составным. это предусмотрено, но крайне не желательно. поэтому я предпочитаю немного посчитать и выделить буфер требуемого объема, который будет рационально загружен (и не будет переполняться) при пиковой загрузке сети. этот сервер уже проверялся и успешно функционирует, выжимая из гигабитного канала максимум производительности. upd: цифры смотри в предыдущей теме. суть в том, что код для каждого клиента получается линеен и не требует сложных алгоритмов поисков.
max7C4, так ёлки, как ты ожидаешь прихода данных? Твой код тянет сотни одновременных клиентов? Ты это тестировал? Как насчёт нескольких сотен клиентов льющик на 28kbps?
до 5000 клиентов на скорости до 200 kbps. загрузка iP4HT 35-40% в зависимости от данных для обработки. и это до сих пор работает
Это бесполезно )) Чувака заклинило. Он уже в стопицотый раз рассказывает про то, о чем его не спрашивают. Если повторить вопрос, то он обижается и бьет себя пяткой в грудь, заявляя, что уже 7.5 лет программирует на ассемблере. Сходу заявляет, что все его метОды "не для языков высокого уровня", о которых он вам не расскажет потому, что вы все равно ничего не поймете, т.к. ассемблера тут кроме него никто не знает.