Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.04.29;
Скачать: CL | DM;

Вниз

Странно ведет себя 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;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.033 c
15-1175409027
Roman_S
2007-04-01 10:30
2007.04.29
Новый компонент без описания и комментариев


15-1175788131
Ricks
2007-04-05 19:48
2007.04.29
Не набираются символы...


15-1175567355
Slider007
2007-04-03 06:29
2007.04.29
С днем рождения ! 3 апреля


15-1175436076
Ccil
2007-04-01 18:01
2007.04.29
Многопользовательские онлайновые игры в рунете


3-1170860196
valua
2007-02-07 17:56
2007.04.29
Хранимая процедура : выбор записей + количество по полю