Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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 вся ветка

Форум: "Начинающим";
Текущий архив: 2011.12.18;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.005 c
2-1315318888
Gu
2011-09-06 18:21
2011.12.18
Dll метод


4-1252399230
Jeyson
2009-09-08 12:40
2011.12.18
одно и тоже консольное приложение работает по разному


2-1315955658
WorkWork
2011-09-14 03:14
2011.12.18
SQL-запрос с диапозоном даты


15-1314617994
Юра Погудин
2011-08-29 15:39
2011.12.18
Проблема с форматированием Windows


2-1315223947
vasiliy87
2011-09-05 15:59
2011.12.18
Вопрос о параметрах интефейсных функций





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский