Форум: "Начинающим";
Текущий архив: 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 в поток серверной нити
Сервер не видит подключения клиента
Клиент сделан на WinSockLen := 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
← →
Евгений07 (2011-09-13 12:15) [41]в первую очередь не надо вызывать VCL из не-VCL потока.
я про Form1.Memo1.Lines.Add.
Вырубил. = 0
← →
Сергей М. © (2011-09-13 12:38) [42]При знаниях на уровне "фурычит - не фурычит" затея с реализацией клиента и сервера непосредственно на WinSock выглядит довольно глупой.
Чем не устроили готовые компоненты - совершенно не понятно)
← →
Вариант (2011-09-13 12:39) [43]
> Евгений07 (13.09.11 10:45) [37]
А твой сервер и не должен видеть клиента, ибо не как сервер он у тебя написан. Читай "Программирование в сетях Windows" Джонса и Оланда. Там пример кода сервера есть для EventSelect модели да и модель select описана.
← →
Евгений07 (2011-09-13 16:53) [44]Вариант (13.09.11 12:39) [43]
СПАСИБО!
Читай "Программирование в сетях Windows" Джонса и Оланда.
СПАСИБО!
Нашел. Автор исходника наверное пошутил, для сервера ловил FD_CONNECT
Книга = супер
Еще раз спасибо
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.12.18;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.005 c