Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2003.01.20;
Скачать: [xml.tar.bz2];

Вниз

Сообщения сокетов   Найти похожие ветки 

 
Repeater   (2002-11-19 11:11) [0]

Вобщем такой вопрос. У меня организуется прозрачная передача данных от сервера к клиенту и обратно через мою прогу. Для каждого оединения создается нить в которой работает такой цикл.

While not cmd_stop Do Begin //Цикл работает до тех пор пока не получим команду завершить
//Ждем пока придет сообщение
res:=WSAWaitForMultipleEvents(2,@Events,False,1000,False);
Case res Of
WSA_WAIT_EVENT_0:Begin //Client
//Смотрим какие сообщения произошли
res:=WSAEnumNetworkEvents(threadsocket, Events[0], @NetEvnt);
//Если ошибка то глушим нить
If res=SOCKET_ERROR Then CloseThread;
//Если надо читать - читаем
If (NetEvnt.lNetworkEvents and FD_READ)>0 Then Begin
ZeroMemory(@buf,SizeOf(Buf));
//берем данные от клиента
rcv:=recv(threadsocket,Buf,Length(Buf),0);
gle:=WSAGetLastError;
if (rcv=0) or (gle=WSAECONNRESET) then CloseThread;
//отправляем серверу
snd:=send(ProxySock,Buf,rcv,0);
gle:=WSAGetLastError;
If snd=SOCKET_ERROR Then If WSAGetLastError<>WSAEINPROGRESS Then CloseThread;
End;
//Если разорвался коннект, то глушим нить
If (NetEvnt.lNetworkEvents and FD_CLOSE)>0 Then CloseThread;
End;
WSA_WAIT_EVENT_0+1:Begin //Server
//Смотрим какие сообщения произошли
res:=WSAEnumNetworkEvents(ProxySock, Events[1], @NetEvnt);
//Если ошибка то глушим нить
If res=SOCKET_ERROR Then CloseThread;
If NetEvnt.lNetworkEvents=0 Then CloseThread;
//Если надо читать - читаем
If (NetEvnt.lNetworkEvents and FD_READ)>0 Then Begin
ZeroMemory(@buf,SizeOf(Buf));
//берем данные от сервера
rcv:=recv(ProxySock,Buf,Length(Buf),0);
gle:=WSAGetLastError;
if (rcv=0) or (gle=WSAECONNRESET) then CloseThread;
//Отправляем клиенту
snd:=send(threadsocket,Buf,rcv,0);
gle:=WSAGetLastError;
If snd=SOCKET_ERROR Then If WSAGetLastError<>WSAEINPROGRESS Then CloseThread;
End;
//Если разорвался коннект, то глушим нить
If (NetEvnt.lNetworkEvents and FD_CLOSE)>0 Then CloseThread;
End;
End;
end; //end while

В принципе все работает. Только иногда нить зависает. То есть не приходят никакие сообщения, хотя один из сокетов уже закрыт. Может я че не так делаю? Почему не приходят эти сообщения?


 
Repeater   (2002-11-19 11:15) [1]

Да, забыл сказать. Ивенты установлены на все события

CliEvent:=WSACreateEvent;
ServEvent:=WSACreateEvent;
res:=WSAEventSelect(ServSock,ServEvent, FD_ALL_EVENTS);
res:=WSAEventSelect(threadsocket,CliEvent, FD_ALL_EVENTS);
Events[0]:=CliEvent;
Events[1]:=ServEvent;


 
Digitman   (2002-11-19 11:32) [2]

Где у тебя обработка события FD_WRITE ? У тебя же неблок.режим !


 
Polevi   (2002-11-19 11:44) [3]

в дополнение к Digitman © (19.11.02 11:32)
//отправляем серверу
snd:=send(ProxySock,Buf,rcv,0);
gle:=WSAGetLastError;
If snd=SOCKET_ERROR Then If WSAGetLastError<>WSAEINPROGRESS Then CloseThread;

где обработка WASEWOULDBLOCK ??
в этом коде при первом-же переполнении буфера winsock поток завершится, а надо сохранять буфер и пытаться отправить его при первом FD_WRITE


 
Digitman   (2002-11-19 12:07) [4]

в дополнение к Polevi © (19.11.02 11:44)

Структура NetworkEvents содержит коды ошибок для каждого из трансп.событий, перечисленных в массиве. Нет смысла запрашивать WSAGetLastError(), ибо, если трансп.метод вызвал ошибку (в т.ч. WASEWOULDBLOCK), возникнет соотв.событие с ненулевым кодом ошибки.


 
Repeater   (2002-11-19 12:18) [5]

Спасибо, буду разбираться.


 
Repeater   (2002-11-19 12:21) [6]

To Digitman
>>Где у тебя обработка события FD_WRITE ? У тебя же неблок.режим !

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


 
Digitman   (2002-11-19 12:48) [7]

send() не является ф-цией, непосредственно осуществляющей передачу. Этот вызов лишь ставит указанные тобой данные в хвост внутренней передающей очереди гнезда, из головы которой по мере готовности трансп.ресурсов ядром Winsock выбираются данные для факт.попытки отправки. При успешной отправке фрагмента данных из головы очереди в хвосте этой же очереди освобождается ровно столько места, сколько успешно отправлено.
Очередь передачи являет собой внутр.буфер в памяти, контролируемой ядром Winsock. Буфер не "резиновый" и имеет определ.размер. Если ты пытаешься вызовом send() поставить в очередь на передачу данные размером большим, чем позволяет "свободное" в дан.момент "место" в хвосте буфера-очереди, Winsock имеет право отвергнуть полностью или частично запрошенные к постановке в очередь данные.
При полном отвержении (*), если код ошибки = WSAEWOULDBLOCK, это означает, что попытку повтора передачи тех же данных тем же send-вызовом можно будет повторить не ранее, чем возникнет событие FD_WRITE, извещающее об освобождении очереди передачи.
При частичном отвержении допустимо повторно вызвать send() для попытки постановки в очередь оставшегося фрагмента отвергнутых в предыдущем send-вызове данных; можно повторять send-вызов в цикле, пока либо все оставшиеся данные не будут поставлены в очередь, либо см. (*)


 
Repeater   (2002-11-21 17:08) [8]

Спасибо за подробное объяснения.
Такой вопрос. Почему у меня сразу на один сокет приходят 2 сообщенеия FD_WRITE и FD_READ. Как их обрабатывать?


 
Digitman   (2002-11-21 17:13) [9]

1-й FD_WRITE просто извещает тебя о готовности буфера передачи гнезда. Можешь его проигногировать, если на этот момент нечего передавать.

FD_READ извещает тебя о том, что буфер приема не пуст и ты можешь попытаться прочитать из него (recv) ожидаемый по логике блок данных (но - оч желательно - не более чем rcvbuf_size)


 
Repeater   (2002-11-21 17:21) [10]

А откуда взять rcvbuf_size?


 
Digitman   (2002-11-21 17:24) [11]

см. WinsockAPI : GetSockOpt()



Страницы: 1 вся ветка

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

Наверх





Память: 0.48 MB
Время: 0.011 c
14-62827
Сергей Макаров
2003-01-01 23:30
2003.01.20
Про ОС на паскале....


3-62408
VS2002
2002-12-26 08:20
2003.01.20
Работа с Data Module Designer


1-62641
Оля
2003-01-09 16:51
2003.01.20
RadioButton


1-62527
geo
2003-01-10 17:35
2003.01.20
Как использовать компоненты написанные на Builder в Delphi?


14-62791
RV
2002-12-31 08:28
2003.01.20
С новым годом!





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский