Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Странно ведет себя WaitForData


SpellCaster ©   (2006-11-01 19:28:00) 

Столкнулся со странным поведением функции 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-03 09:38:00) [1]


> SpellCaster   (02.11.06 17:29) [18]


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

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


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

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

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

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


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


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


В сад.

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


medved_68   (2006-11-02 15:51:00) [4]


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

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


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

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

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

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


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


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


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

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


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

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


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


> SpellCaster   (02.11.06 15:02) [11]


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

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

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


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

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


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


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


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

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

?


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

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

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

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

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


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


> SpellCaster   (02.11.06 13:44) [7]



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


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

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

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

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

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

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


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

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

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


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


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


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

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

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


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

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

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 10:53:00) [16]

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


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

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


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


> Функция 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:26:00) [19]


> Функция 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


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


Наверх

Титульная страница Поиск, карта сайта Написать письмо