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

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

Вопрос про сокеты, а точнее про FD_CLOSE и FD_READ [D6, Win95/98, WinME, Win2k, WinXP]


Страницы:   1 2 3

__Unnamed__ ©   (2007-10-01 17:52:00) 

Сделал сервак на основе сокетов. Использовал WS Api функции. Обработка информации происходит следуюющим образом:

Да это все в потоке :)

While not Terminated do
 Begin
    Res:=WaitForMultiPleObjects(1,FSockEvent,False,100,Flase);
    Case Res Of
      0: Begin
             ...
              <здесь проверяю флаги>
              FD_CLOSE
              FD_READ
              FD_WRITE
             ...
          End;
    End;
 End;
Суть вопроса! :)
Выявил следующую ошибку.
Когда передаю большой файл >1Mb по нескольким соединениям(т.е. различные файлы, но соединений более 1-го) иногда не доходит до получателя последний блок. Экспериментальным путем выявил, что  FD_Close приходит раньше, чем FD_READ.
Т.к. сервер не мой (т.е. не мною писанный). логика сервера заключается в том, что при посылке конечного куска файла он завершает соединение Shutdown + CloseSocket Или просто CloseSocket (Онное мне не известно).
Как я помню из сокетов на основе оконных функций FD_CLOSE приходит всегда после того как прийдет последний байт из буфера чтения.
Еще прочитал про критические секции, возможно в этом решение. Т.к. при изучении модуля ScktComp обнаружил, что  любая операция I/O заключена в Enter и Leave.
Скажите не потеряется ли быстродействие и независимость самого потока при использовании критических секций.
Или же моя ошибка заключается в другом? :)


Palladin   (2009-03-12 08:28:00) [1]


> FireMan_Alexey   (04.02.09 18:29) [43]

А ничего что год прошел? :)


!"№;%:?*   (2009-03-12 07:30:00) [2]

При известном количестве данных - читай сколько указано в заголовке, recv вернет ошибку если соединение будет закныто раньше.

В отдельном потоке, можно и блокирующими сокетами обойтись.


FireMan_Alexey   (2009-02-04 18:29:00) [3]

Сделай так:

While True do
Begin
 Err:=Recv(...);
 IF err=SOCKET_ERROR and WSAGetLastError=WSAEWOULDBLOCK Then
   Break;
End;
Event - сигнализирует о приходе данных, а IOCTLSocket - покажет всего 8192 макс хотя там может быть и больше :) (проверенно экспериментально)
А вообще лучше использовать Select в потоках :) тоже экспериментально :)
Я тоже пытался прокси на Эвентах написать, но столкнулся с такой же ситуацией и с не закрытыми соединениями со стороны апачей :).
Спасло только то что весь код переделал под синхронные сокеты.


  (2009-02-04 17:32:00) [4]

Удалено модератором


ага   (2008-02-06 13:22:00) [5]

Просмотрел бегло, может уже сказано, но не заметил.

Нормально это, FIN пришел вместе с последним пакетом. Сервер закончил запись и вызвал shutdown на свой передающий конец - типа больше ниче передавать не буду. Сокет отправил все из буфера и с последним пакетом - FIN. Получив его, нужно вычерпать все из буфера и закрыть свой приемный конец.


  (2008-02-05 19:35:00) [6]

Удалено модератором


Сергей М.   (2007-10-05 08:58:00) [7]

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


> мне прийдется анализировать
> <Content-length:?????>


Да, придется.


__Unnamed__   (2007-10-04 20:28:00) [8]

Скажи, а если у меня происходит скажем задержка потока на 1-5 секунды в связи с записью на устройство. И чтение из буфера приемника задерживается, то по логике TCP FIN прийдет только тогда, когда Апач полностью передаст данные, ну или у него SO_LINGER=False и прийдет дисконнект но в буфере приемника может быть где-то до 8-64Кб информации как я понимаю.

И мне кажеться в моем случае, мне прийдется анализировать
<Content-length:?????> + FD_CLOSE и его ошибки. Если при дисконнекте произошли ошибки, то выходить иначе читать до тех пор пока не будет равно ожидаемого.


Сергей М.   (2007-10-04 13:16:00) [9]

Подозреваю, что где-то что-то ты недопонимаешь.

Вряд ли Апач будет рвать соединение не передав полностью запрошенные у него данные, если на то нет веских причин.

Пробуй ту же логику в блокирующем режиме. Если все будет ок, то неправ ты, иначе Апач.


Сергей М.   (2007-10-04 13:12:00) [10]

Это, в свою очередь, зависит от Interval.


__Unnamed__   (2007-10-04 13:01:00) [11]

Т.е. при SO_LINGER = TRUE с моей стороны, все данные будут приняты?
Или это только для посылки?


Сергей М.   (2007-10-04 12:51:00) [12]

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


__Unnamed__   (2007-10-04 12:49:00) [13]

>>Сергей М. ©

Ну так первым дело м при этом ты должен был искать в списке событий, возвращенных вызовом этой ф-ции, событие FD_READ и только потом FD_CLOSE, но не наоборот.


См. топик [9]!!!


Сергей М.   (2007-10-04 12:48:00) [14]


> когда я не выполняю ShutDown сам Апаче сервер не закрывает
> со своей стороны Гнезда и ждет непонятно чего


Быть того не может.

Если ты выполнил без ошибок closesocket, то рано или поздно партнер получит FIN.


__Unnamed__   (2007-10-04 12:47:00) [15]

Я столкнулся с такой проблемой, когда я не выполняю ShutDown сам Апаче сервер не закрывает со своей стороны Гнезда и ждет непонятно чего??!!!!!
А с ShutDown все нормально :)


Сергей М.   (2007-10-04 12:46:00) [16]


> я так и делал


Ну так первым дело м при этом ты должен был искать в списке событий, возвращенных вызовом этой ф-ции, событие FD_READ и только потом FD_CLOSE, но не наоборот.


Сергей М.   (2007-10-04 12:44:00) [17]


> Как можно проверить с каким пар-ром ShutDown был выполнен
> с серверной стороны?


Кроме анализа текста сервера - никак.
Кстати, Апач - опенсурсный продукт.


> Я со своей стороны выполняю всегда ShutDown(FServerS, ??
> _BOTH);


Нафига ?


__Unnamed__   (2007-10-04 12:42:00) [18]

Ну и CloseSocket после ShutDown соотвественно :)


__Unnamed__   (2007-10-04 12:42:00) [19]

1. Сервер Apache но локально(хотя это не имеет значения)
2. Рекомендации Slym-а смотрел см [9], я так и делал просто когда писал вопрос, первое что в голову пришло это было FD_CLOSE :)

Как можно проверить с каким пар-ром ShutDown был выполнен с серверной стороны? Я про это еще нигде не видел примеров и статей :)
Я со своей стороны выполняю всегда ShutDown(FServerS, ??_BOTH);


Сергей М.   (2007-10-04 12:42:00) [20]

Короче, сервер вполне м.б. "кривым".

Ну а твоя "кривизна" как клиента исправляется задействованием WSAEnumNetWorkEvents


Страницы:   1 2 3

Наверх

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