Страницы: 1 2 вся ветка
Форум: "Начинающим";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2011.12.18;
Скачать: [xml.tar.bz2];




Вниз

WSAWaitForMultipleEvents для однонитевого сервера 


Евгений07   (2011-09-09 16:14) [0]

Уважаемые дельфийцы!
Есть ли примеры использования WSAWaitForMultipleEvents для запуска процедуры приема и обработке данных однонитевым  сервером от единственного клиента ( WinSock2 )
Событие об отправке данных серверу через PostMessage, были случаи, терялись.
Номер сообщения получен из RegisterWindowMessage.
Возможно, клиент и сервер будут на разных компах, тогда PostMessage отпадает.
Заводить процесс только для WSAWaitForMultipleEvents для единственного клиента сервера не хочется, нет практики, потребности и времени.
Как вариант есть еще таймер
Где посоветуете копать?



Юрий Зотов ©   (2011-09-09 17:14) [1]

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



Евгений07   (2011-09-09 17:58) [2]

Юрий!
С потоком я знаком теоретически, а запускать в объемные проги вещь не подробно изученную - грабли знакомые.
Нужна простая вещь.
Как последний вариант сейчас прорабатываю таймер с переменным временем.
Прогнозируемое время поступления инфы от клиента есть.
Запрос клиенту идет после проглота сервером инфы клиента.
Хотелось бы простой обработчик события, сервер с окном



Сергей М. ©   (2011-09-09 18:01) [3]

После чтения справки что-то непонятно в параметрах и логике работы WSAWaitForMultipleEvents ?



Евгений07   (2011-09-09 18:51) [4]

Сергей М.
Ясно что WSAWaitForMultipleEvents это поток.
В моей ситуации поток = грабли, на которые я наступлю.
+ выделение из большой однопоточной и много раз переработанной проги куска в поток сервера не вызывает энтузиазма.

Остается:
1. хитромудрое использование WSAWaitForMultipleEvents без потока помимо справки
2. Событие таймера с переменным временем.
3. Чюдо = то чего не знаю, но очень нужное и простое

Искать кто мог сожрать PostMessage или ковырять WSAasyncselect из-за возможности разноса клиента и сервера по разным компам тоже не вдохновляет



Сергей М. ©   (2011-09-09 20:02) [5]


> Ясно что WSAWaitForMultipleEvents это поток


Чавой-то ?
Поясни свою глубокогениальную мысль ..



Inovet ©   (2011-09-09 20:10) [6]

> [2] Евгений07   (09.09.11 17:58)
> Как последний вариант сейчас прорабатываю таймер с переменным временем.

Есть нормальный механизм, нет надо ректально сделать.



Евгений07   (2011-09-09 22:24) [7]

Сергей М. ©   (09.09.11 20:02) [5]
> Ясно что WSAWaitForMultipleEvents это поток

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

FEventClose := WSACreateEvent;
WSAEventSelect(Socket,FEvent, FD_CLOSE + FD_READ );
repeat
WaitForSingleObject(FEvent,INFINITE);
WSAEnumNetworkEvents(FSocket,FEvent,@NI);
case NI.lNetworkEvents of
FD_Close:break;
FD_Read: begin
ReceiveData;
end;
end;
WSAResetEvent(FEventClose);
Until false;


Только для получения события обработки данных.

Проблема в том что из СТАРОГО комплекса РАБОЧИХ прог с многолетними заплатками, и кардинальными переделками, примерно 25 файлов немалого кода каждый,  некоторые файлы входят во ВСЕ проги, некоторые в часть прог я должен выдернуть кусок и поместить его в отдельный процесс

Нужен простой выход.
Не ломай что работает.
Уяснил.



Евгений07   (2011-09-09 22:43) [8]

Inovet ©   (09.09.11 20:10) [6]
> [2] Евгений07   (09.09.11 17:58)
> Как последний вариант сейчас прорабатываю таймер с переменным временем.
Есть нормальный механизм, нет надо ректально сделать.


Слово ректально .... ректально
К употребленному ( + унутрь)  + слову могу предположить не медицинское назначение предложения, хотя медицинский спирт не противоречит моей концепции.
Но ХОРОШИЙ виски лучше.

Какой нормальный механизм мне поможет вылезти из моей ситуации.



Евгений07   (2011-09-09 22:57) [9]

Перечитал написанное.
Коррекция [7]
к Сергей М. © [5]
Прошу читать
Уяснил
 как
Я за время своей работы я уяснил для себя любимого:
Нужен простой выход из ситуации.
Не ломай что работает.



Inovet ©   (2011-09-09 22:57) [10]

> [8] Евгений07   (09.09.11 22:43)
> Какой нормальный механизм мне поможет вылезти из моей ситуации.

Я уже понял, что много выгребать надо.



Евгений07   (2011-09-09 23:56) [11]

Inovet ©  
Мне много не надо
Где лучше копать?



Евгений07   (2011-09-10 00:14) [12]

Inovet ©
уточнение
Мне много не хочу.
Где зацепиться:
1. 2. 3. из пп  [4] или что то еще ЧЮДО



Германн ©   (2011-09-10 00:57) [13]


> Я уже понял, что много выгребать надо.
>

А я ещё понял, что код чужой. Т.е. совсем всё плохо для ТС. :(



Евгений07   (2011-09-10 07:30) [14]

Германн ©
Код свой.
Но старый.
Лучше скажи где копать, Германн



Сергей М. ©   (2011-09-10 17:25) [15]


> Для обслуживания серверного сокета я должен создать отдельный
> поток


Да ничего никому ты не должен, не выдумывай небылиц)

Выкидываешь в топку WSAWaitForMultipleEvents, пользуешь вместо него с тем же успехом MsgWaitForMultipleObjects и проблема твоя решена в том же самом единственном основном потоке - и на гнездовые события реагируешь и на виндовые сообщения.



Вариант   (2011-09-12 08:58) [16]


> Евгений07   (09.09.11 16:14)


> Где посоветуете копать?

Если по человечески хочешь в одном потоке, то использовать вместо WSAEventSelect -> WSAAsyncSelect, естественно сначала почитать, что это даст...



Евгений07   (2011-09-12 09:56) [17]

Доброго всем времени!
Копнул таймер. Сервер жрет 50% ЦП в моем случае

WSAAsyncSelect = пробовал PostMessage были случаи потерь событий об отправке данных серверу  

Вопрос:

много ли будет жрать ЦП в случае WSAWaitForMultipleEvents  или MsgWaitForMultipleObjects



Evgeny V   (2011-09-12 10:18) [18]


> Евгений07   (12.09.11 09:56) [17]
> WSAAsyncSelect = пробовал PostMessage были случаи потерь
> событий об отправке данных серверу  

Потери скорее всего у тебя в логике программы. Надо обрабатывать и результаты возврата функций.


> много ли будет жрать ЦП в случае WSAWaitForMultipleEvents
>  или MsgWaitForMultipleObjects


Лишнего не сожрет, от твоих ошибок не застрахует



Евгений07   (2011-09-12 10:30) [19]

Evgeny V   (12.09.11 10:18) [18]

 WM_PewFor_Arx  := RegisterWindowMessage("WM_PewFor_Arx ");

procedure TForm1.WndProc(var Message: TMessage);            
 if Message.Msg = WM_PewFor_Arx then begin
    //обработка команда терминала FxPew = сервер
   // здесь были случаи потери, ктото хавал раньше
 end else
   inherited WndProc(Message)



Evgeny V   (2011-09-12 11:03) [20]


> Евгений07   (12.09.11 10:30) [19]

1) Какое это имеет отношение к WSAAsyncSelect? Думаешь будут теряться сообщения?
2) Потери сообщений на совести логики твоей программы.



Evgeny V   (2011-09-12 11:03) [21]


> Евгений07   (12.09.11 10:30) [19]

1) Какое это имеет отношение к WSAAsyncSelect? Думаешь будут теряться сообщения?
2) Потери сообщений на совести логики твоей программы.



Евгений07   (2011-09-12 11:55) [22]

Факты потери были. Несколько раз, плавающие
На отладочной форме был Мемо для трассировки и Чек для управлением объема отладки.
Если щелкание кнопками сервера я могу сбить факт прихода сообщения клиента  этого не должно быть



Evgeny V   (2011-09-12 12:00) [23]


> Евгений07   (12.09.11 11:55) [22]


> Если щелкание кнопками сервера я могу сбить факт прихода
> сообщения клиента  этого не должно быть

Если ты щелканьем кнопки добиваешься потерь сообщений - это говорит только об ошибке в программе. Если это так легко воспроизводится- то код в студию.



Евгений07   (2011-09-12 13:02) [24]

Для воспроизведения надо стороннюю прогу + моя ДЛЛ с клиентом + отладчик сервера

Пока проверил версию с потоком
WSAWaitForMultipleEvents Жрет > 50% ЦП  как и вариант с таймером

Это плохо, у меня на компе с интернетом еще 1 сервер

Вопрос: выводы верны?
1. сервер с потоком на WSAWaitForMultipleEvents жрет  > 50% ЦП
2. сервер с таймером жрет  > 50% ЦП

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



Evgeny V   (2011-09-12 13:26) [25]


> Евгений07   (12.09.11 13:02) [24]

В режиме ожидания WSAWaitForMultipleEvents ничего не жрет. Я использовал в своих программах и WsaAsyncSelect и WSAWaitForMultipleEvents, сама функция(WSAWaitForMultipleEvents) в режиме ожидания не жрет ничего. Проблема  в коде дальнейшем.



Inovet ©   (2011-09-12 13:38) [26]

> [24] Евгений07   (12.09.11 13:02)

Она на то и Wait, чтобы не жрать ничего до события, как и таймер до заданного интервала.



Evgeny V   (2011-09-12 13:46) [27]


> Inovet ©   (12.09.11 13:38) [26]

Если только он не задал интервал ожидания 0 например. Вываливается сразу и грузит систему вечным опросом с маленьким интервалом.
Но партизаны строк проблемного кода не дают.....



Евгений07   (2011-09-12 13:52) [28]

Взял стандартную прогу с инета

procedure SocketProc;
var
 hEvent,Event: WSAEVENT;
 NetworkEvents: TWSANetworkEvents;
begin
//==============================================================================
  hEvent:= WSACreateEvent;
  if hEvent = WSA_INVALID_EVENT then Exit;
  if WSAEventSelect(AcceptedSock, hEvent,
                     FD_CONNECT or FD_WRITE or
                     FD_READ or FD_CLOSE) = SOCKET_ERROR then Exit
   else begin
     while True do begin
       Event:= WSAWaitForMultipleEvents(1, @hEvent, False, WSA_INFINITE, False);   //
   if ((NetworkEvents.lNetworkEvents and FD_READ)<>0) then begin
     if (NetworkEvents.iErrorCode[FD_READ_BIT]<>0) then begin
       WriteLn("FD_READ failed with error: " + IntToStr(NetworkEvents.iErrorCode[FD_READ_BIT]));
       Break;
     end else begin
 Form1.SocketBar;      // здесь вызов рабочий, правда через селект, простой код
     end;
   end;



У меня ожидания обычно до минуты
terminal.exe 50 - 54 % времени ЦП

Если запуск вручную кнопкой, Цп 1 - 0 %, запуск через PostMessage Цп 1 - 0 %



Евгений07   (2011-09-12 14:05) [29]

Значение WSA_INFINITE не посмотрел, но задал 1000 мс те же 50 %



Evgeny V   (2011-09-12 14:15) [30]


> Евгений07   (12.09.11 14:05) [29]

WSA_INFINITE - ждать пока не произойдет событие.
А прога у тебя или скопирована кусками или с ошибками так и была. Ты создал событие, которое должно сбрасываться вручную.... Ты получил сетевое событие, не сбросил и снова вошел в цикл ожидания, а событие-то в сигнальном состоянии  еще/уже, значит сразу вывалился и опять все то же самое по бесконечному циклу без перерыва(где WSAResetEvent). Ошибка однако.



Evgeny V   (2011-09-12 14:16) [31]

Да и анализа на WSA_WAIT_FAILED нет



Evgeny V   (2011-09-12 14:26) [32]

Кстати еще - как сочетается
> Form1.SocketBar

и
> Пока проверил версию с потоком

Если работа идет в разных потоках - то это тоже ошибка



Evgeny V   (2011-09-12 14:30) [33]

И дальше, а кто собственно заполняет NetworkEvents (где WSAEnumNetworkEvents )?



DiamondShark ©   (2011-09-12 19:53) [34]

……………………………………
……………………………………
……………………………………
……………………………………..________
………………………………,.-‘”……………….“~.,
………………………..,.-”……………………………..“-.,
…………………….,/………………………………………..”:,
…………………,?………………………………………………\,
………………./…………………………………………………..,}
……………../………………………………………………,:`^`..}
……………/……………………………………………,:”………/
…………..?…..__…………………………………..:`………../
…………./__.(…..“~-,_…………………………,:`………./
………../(_….”~,_……..“~,_………………..,:`…….._/
……….{.._$;_……”=,_…….“-,_…….,.-~-,},.~”;/….}
………..((…..*~_…….”=-._……“;,,./`…./”…………../
…,,,___.\`~,……“~.,………………..`…..}…………../
…………(….`=-,,…….`……………………(……;_,,-”
…………/.`~,……`-………………………….\……/\
………….\`~.*-,……………………………….|,./…..\,__
,,_……….}.>-._\……………………………..|…………..`=~-,
…..`=~-,_\_……`\,……………………………\
……………….`=~-,,.\,………………………….\
…………………………..`:,,………………………`\…………..__
……………………………….`=-,……………….,%`>–==“
…………………………………._\……….._,-%…….`\
……………………………..,<`.._|_,-&“…………….`\



Сергей М. ©   (2011-09-12 20:05) [35]

Ну точно белочка)



Евгений07   (2011-09-12 20:10) [36]

Совет не поменять WSAWaitForMultipleEvents на голову принят



Евгений07   (2011-09-13 10:45) [37]

Доброго времени, мастера!
Нашел пожирателя ЦП - это клиент, не получавший подтверждения
Evgeny V   (12.09.11 14:26) [32]
Если работа идет в разных потоках - то это тоже ошибка

Сейчас переписал SocketBar в поток серверной нити
Сервер не видит подключения клиента

Клиент сделан на WinSock
   Len := SelectFDSet;          
   Len := connect (Sockett, Addr, SizeOf(TSockAddr) ) ;
, , ,
   if FD_IsSet(Sockett, FDSetR) or FD_IsSet(Sockett, FDSetW)
   then begin
Res := PostMessage(wnd, WM_PewForArx, 1, 2); // открытка подключения = принята
     if not Res then
       OperSocet := 1  //сбой
     else begin
       OperSocet := 10;  // работа = работает
     end;
   end;  
 if (OperSocet >= 10) // ...
 then begin                             //
   Len := SelectFDSet;          
   if FD_IsSet(Sockett, FDSetR) then  begin
// = здесь тишина
   end;
 end;  

Сервер не видит коннекта
 hEvent:= WSACreateEvent;
 if hEvent = WSA_INVALID_EVENT then Exit;
 Flags := SOCKET_ERROR;
 Flags := WSAEventSelect(Sockett, hEvent, FD_WRITE or FD_READ or FD_CONNECT or FD_CLOSE);
 if Flags = SOCKET_ERROR then Exit
 else while True do begin
   Event:= WSAWaitForMultipleEvents(1, @hEvent, False, WSA_INFINITE, False);   //
   if (Event = WSA_WAIT_FAILED) then begin
         Break;
   end;
   if (WSAEnumNetworkEvents(Sockett, hEvent, @NetworkEvents) = SOCKET_ERROR)
   then begin
         Form1.Memo1.Lines.Add("WSAEnumNetworkEvents() failed with error: " + IntToStr(WSAGetLastError));
         Break;
   end;
   WSAResetEvent(hEvent);  

   if ((NetworkEvents.lNetworkEvents and FD_CONNECT)<>0) then begin
     if (NetworkEvents.iErrorCode[FD_CONNECT_BIT]<>0) then begin
       Form1.Memo1.Lines.Add("FD_CONNECT failed with error:"  + IntToStr(NetworkEvents.iErrorCode[FD_CONNECT_BIT]));
       Break;
     end else begin
       Len := SizeOf(TSockAddr);
       AcceptedSock := Accept(Sockett, Addr, Len);
       if AcceptedSock = Invalid_Socket then begin    
         Form1.Memo1.Lines.Add("FD_CONNECT failed with error:"  + IntToStr(NetworkEvents.iErrorCode[FD_CONNECT_BIT]));
         Break;
       end else begin
         OperSocet := 10;  
       end;
       Form1.Memo1.Lines.Add("Connect socket: " + IntToStr(Sockett));
     end;
   end;

Может я зря пробую подключать коннект в дополнительной нити?
Если подключать коннект в основной нити, то что то фурычит.
Тогда как ждать коннект?
Или в клиенте делать WSAConnect?



RWolf ©   (2011-09-13 11:00) [38]

в первую очередь не надо вызывать VCL из не-VCL потока.
я про Form1.Memo1.Lines.Add.



Вариант   (2011-09-13 11:32) [39]


> Евгений07   (13.09.11 10:45) [37]

Возьми TServerSocket на закладке интернет и не мучайся, будет у тебя все вызываться в основном потоке. И почитай хелп по кмопонентам и обязательно литературу по TCP и потокам. Все равно надо это сделать, почему не сделать это сейчас.



Вариант   (2011-09-13 11:37) [40]


> Вариант   (13.09.11 11:32) [39]


Не TServerSocket, a TClientSocket




Страницы: 1 2 вся ветка
Форум: "Начинающим";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2011.12.18;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.83 MB
Время: 0.039 c
2-1315253407      Captcha               2011-09-06 00:10  2011.12.18  
Программный выбор элемента в ComboBox


3-1268739476      Rob                   2010-03-16 14:37  2011.12.18  
СУБД с возможностью хранения текстовых документов в сжатом виде.


2-1315226772      rammic                2011-09-05 16:46  2011.12.18  
Получение данных из 3ds Max


2-1315288804      TrashReg              2011-09-06 10:00  2011.12.18  
Ключи реестра Windows


1-1277278827      azatsh                2010-06-23 11:40  2011.12.18  
как открыть dll засунутую вexe шник как ресурс