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

Вниз

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

 
SpellCaster   (2006-11-01 19:28) [0]

Столкнулся со странным поведением функции WaitForData в клиентском приложении. Что делаю: запускаю сервер, запускаю клиента. Клиент соединяется и принимает данные, а потом я останавливаю сервер. По идее, WaitForData должна ставить нить на ожидание, а по истечении времени - сообщать, что в канале ничего нет. Однако этого не происходит, и функция возвращает True.
Вот WaitForData, слямзенная из TWinSocketStream

function TClientThread.WaitForData(Timeout: Longint): Boolean;
var FDSet: TFDSet;     // структура - список сокетов
   TimeVal: TTimeVal; // время, сколько ждать
begin
TimeVal.tv_sec:=Timeout div 1000;           // время в с
TimeVal.tv_usec:=(Timeout mod 1000)*1000;   // время в мс
FD_ZERO(FDSet);                             // обнуляем структуру
FD_SET(fClient.Socket.SocketHandle, FDSet); // заносим хэндл
Result:=Select(0,@FDSet,nil,nil,@TimeVal)>0;
end;


и функция чтения


// Чтение Cnt байт из буфера сокета
function TClientThread.ReadBytes(var Buf; Cnt: Integer=1): Integer;
begin
if WaitForData(5000) then // !! вот здесь всё проходит на ура
 Result:=fClient.Socket.ReceiveBuf(Buf,Cnt)  // !! а здесь возвращает -1
else
begin WriteLog("Таймаут ожидания данных",mkErr); Result:=-1; end; // !! а сюда не попадает!
end;


Функция Select возвращает 1. В чём могут быть грабли?


 
Сергей М. ©   (2006-11-02 08:26) [1]


> Функция Select возвращает 1. В чём могут быть грабли?


С чего ты взял, что это "грабли" ?

select() сообщила тебе, что в указанном тобой гнезде произошло некое событие, в твоем случае - разрыв соединения по инициативе партнера.

Читаем справку:

readfds:

· If listening, a connection is pending, accept will succeed
· Data is available for reading (includes OOB data if SO_OOBINLINE is enabled)
· Connection has been closed/reset/terminated


> Result:=fClient.Socket.ReceiveBuf(Buf,Cnt)  // !! а здесь
> возвращает -1


Абсолютно нормально. Соединение-от на этот момент уже разорвано !


 
Сергей М. ©   (2006-11-02 08:27) [2]


> Функция Select возвращает 1. В чём могут быть грабли?


С чего ты взял, что это "грабли" ?

select() сообщила тебе, что в указанном тобой гнезде произошло некое событие, в твоем случае - разрыв соединения по инициативе партнера.

Читаем справку:

readfds:

· If listening, a connection is pending, accept will succeed
· Data is available for reading (includes OOB data if SO_OOBINLINE is enabled)
· Connection has been closed/reset/terminated


> Result:=fClient.Socket.ReceiveBuf(Buf,Cnt)  // !! а здесь
> возвращает -1


Абсолютно нормально. Соединение-от на этот момент уже разорвано !


 
SpellCaster   (2006-11-02 10:48) [3]

Так, ясненько. А внутри WaitForData можно как-то определить, что в данном случае произошел именно Connection has been closed/reset/terminated, а не Data is available for reading?


 
Сергей М. ©   (2006-11-02 10:53) [4]

см. параметр exceptfds ф-ции select()


 
SpellCaster   (2006-11-02 13:12) [5]

Посмотрел, видоизменил функцию:

function TClientThread.WaitForData(Timeout: Longint): Boolean;
var FDReadSet,FDExcSet: TFDSet;     // структура - список сокетов
   TimeVal: TTimeVal; // время, сколько ждать
begin
TimeVal.tv_sec:=Timeout div 1000;           // время в с
TimeVal.tv_usec:=(Timeout mod 1000)*1000;   // время в мс
FD_ZERO(FDReadSet);                             // обнуляем структуру
FD_SET(fClient.Socket.SocketHandle, FDReadSet); // заносим хэндл
FD_ZERO(FDExcSet);                             // обнуляем структуру
FD_SET(fClient.Socket.SocketHandle, FDExcSet); // заносим хэндл
Res:=Select(0,@FDReadSet,nil,@FDExcSet,@TimeVal);
Result:=res>0;
end;


FDExcSet.fd_count равняется нулю. Пробовал заполнять writefds - возвращает 1, т.е. всё ОК.


 
Сергей М. ©   (2006-11-02 13:28) [6]


> FDExcSet.fd_count равняется нулю


Э-э-э ... извиняюсь, я соврал тебе.

exceptfds не имеет отношения к событиям дисконнекта.

В целом и общем select() не позволяет получить такую инф-цию.


 
SpellCaster   (2006-11-02 13:44) [7]

> [6] Сергей М. ©   (02.11.06 13:28)

Ничего, бывает. Наверно, легче всего будет просто сделать несколько попыток чтения через некоторый интервал, и если все они оказываются неудачными (-1), дисконнектить сокет. Как думаешь?


 
Сергей М. ©   (2006-11-02 14:07) [8]


> SpellCaster   (02.11.06 13:44) [7]



> Как думаешь?


Думаю что ты усложняешь понимание проблемы и решение задачи.

У тебя гнездо работает в блок. режиме.

Это означает, что первая же попытка вызова ф-ции чтения из гнезда, вернувшая -1, есть факт произошедшего краха соединения (по тем или иным причинам - неважно каким).

Следовательно, нет никакого резона в дальнейшем продолжать эти попытки, ибо крах соединения налицо. Следует уничтожить гнездо.

Но мне непонятна твоя смесь из готовой логики компонента TClientSocket и WinsockAPI.

Чем эта "смесь" оправдана ? Поясни ...


 
SpellCaster   (2006-11-02 14:42) [9]

> У тебя гнездо работает в блок. режиме.
> Это означает, что первая же попытка вызова ф-ции чтения
> из гнезда, вернувшая -1, есть факт произошедшего краха соединения
> (по тем или иным причинам - неважно каким).
> Следовательно, нет никакого резона в дальнейшем продолжать
> эти попытки, ибо крах соединения налицо. Следует уничтожить
> гнездо.

Логично! Пожалуй, так и сделаю.

> Чем эта "смесь" оправдана ? Поясни ...

Видимо, тем, что у TClientSocket нет метода WaitForData. Так бы я не полез в дебри, да я и сейчас не лезу, просто взял процедурку из другого класса. Без таймаута не хочется, перспектива иметь проблемы с зависшими в случае неполадок потоками как-то не внушает оптимизма.


 
Сергей М. ©   (2006-11-02 14:52) [10]


> у TClientSocket нет метода WaitForData


Ну так а чем же неблок.режим не устроил ?

Ведь в этом режиме ты совершенно не ограничен в контроле за временем исполнения транспортной операции ..

?


 
SpellCaster   (2006-11-02 15:02) [11]

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


 
Сергей М. ©   (2006-11-02 15:05) [12]


> SpellCaster   (02.11.06 15:02) [11]


Никаких "хитросплетений событий" в неблок.режиме не существует. ты их выдумал.

Равно как и выдумал проблему с контролемс за состоянием транспорта в блок.режиме.

Короче, ты пытаешься высосать из пальца несуществующую проблему.


 
SpellCaster   (2006-11-02 15:25) [13]

Ничего я не пытаюсь, мне и так проблем хватает =). Ну не нравится мне неблок, и всё. А контроля за траспортом тоже никакого нету, есть только выход по таймауту и слежение за результатом чтения. Так что жизнь прекрасна... до следующего бага ). Данная тема исчерпана, благодарю за помощь =)


 
Сергей М. ©   (2006-11-02 15:34) [14]


> контроля за траспортом тоже никакого нету


Потому что эт тебе не два проводка, соединяющих батарейку и лампочку на уроках элементарной физики 7-го класса.

Понятие происходящего в TCP-транспорте приходит с внимательным изучением происходящего при этом. И, разумеется, при понимании роли TCP в модели OSI.


 
SpellCaster   (2006-11-02 15:46) [15]

> Понятие происходящего в TCP-транспорте приходит с внимательным
> изучением происходящего при этом.

Вот загнул ))).

Но я согласен, до нормального понимания внутренностей протоколов и сокетов мне еще далеко.


 
medved_68 ©   (2006-11-02 15:51) [16]


> Видимо, тем, что у TClientSocket нет метода WaitForData.

SpellCaster   А почему бы не прикрутить к TClientSocket TWinSocketStream у которого сей метод есть???? :)


 
Сергей М. ©   (2006-11-02 16:19) [17]


> SpellCaster   (02.11.06 15:46) [15]
>
> > Понятие происходящего в TCP-транспорте приходит с внимательным
> > изучением происходящего при этом.
>
> Вот загнул ))).


В сад.

Ты НЕ хочешь разобраться в происходящем.


 
SpellCaster   (2006-11-02 17:29) [18]

> [16] medved_68 ©   (02.11.06 15:51)
Да не хочется лишний объект создавать, легче функцию слямзить.

> [17] Сергей М. ©   (02.11.06 16:19)

В чём-то ты прав, мне не очень охота глубоко вникать в технологии. И так забот хватает. НО дело не в этом. Меня поставила в тупик твоя фраза. При чём "при этом"? При TCP-транспорте? Или же "Понятие Х приходит с внимательным изучением Х" ? Ну, с этим-то не поспоришь, и я обеими руками за.


 
Сергей М. ©   (2006-11-03 09:38) [19]


> SpellCaster   (02.11.06 17:29) [18]


Почитай хотя бы вот это

http://book.itep.ru/4/44/tcp_443.htm



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

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

Наверх





Память: 0.5 MB
Время: 0.039 c
9-1148749051
DevilDevil
2006-05-27 20:57
2007.04.29
Как совмещать 3D & 2D


2-1176281435
Лёля
2007-04-11 12:50
2007.04.29
ZTable - grid


15-1174989221
zdm
2007-03-27 13:53
2007.04.29
шашки


1-1173168166
Ques
2007-03-06 11:02
2007.04.29
SetErrorMode(SEM_FAILCRITICALERRORS) для приложения


2-1176292688
Priest
2007-04-11 15:58
2007.04.29
Как проверить наличие поддерева в XML





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