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

Вниз

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

 
Jolik   (2004-08-05 13:32) [0]

Вот сколько получено я могу запросить у сокета (через ioctrl), а как узнать сколько я могу записать в асинх.сокет? Ведь у виндов тоже свои буфера в АйПи стеке есть... Если я неограниченно много начну записывать, они ведь должны переполниться. или я что-то не понимаю...


 
Digitman ©   (2004-08-05 13:36) [1]

ты не волнуйся за это - ф-ция send() вернет тебе результатом число реально записанных байт в буфер передачи


 
Jolik   (2004-08-05 14:51) [2]

Я тк понимаю:
send на асинхронном сокете может вернуть WSAEWOULDBLOCK - это значит, я сейчас ниче передавать не буду, а передам когда у меня будет время. При этом буфер с данными переданный в send копируется в системные буфера АйПи стека и передается когда появится возможность. Т.е. для программиста это все равно что полностью передано. Так вот, если быстро толкать данные, send постоянно возвращает WSAEWOULDBLOCK (т.е. буферирует мои данные до лучших времен), и до каких пор?
А если напередавал я из файла 256 кБайт важнейшей информации, которая сбуферировалась в стеке АйПи. файл удалил. А соединение возьми и разорвись. Где теперь мои данные? Как узнать, сколько успело передаться? 100 байт или 100 килобат?
Спасибо!


 
Rouse_ ©   (2004-08-05 15:16) [3]

send вернет тебе количество байт помещенных в буффер
если send вернул WSAEWOULDBLOCK значит пока еще идет передача (буффер не пуст), в этом случае ожидай FD_WRITE которое сообщит тебе о завершении передачи данных.
А еще лучше воспользоваться моделью перекрытого ввода-вывода, а именно WSASend. Я обычно пользуюсь WSASend с процедурами завершения а не уведомлении о собвтии. но это тебе решать. Факт, что она тебе сама сообщит о окончании передачи или о ошибке а также о количестве байт перемещенных во время операции...


 
Anatoly Podgoretsky ©   (2004-08-05 15:21) [4]

Это поток, количество не ограничено, хоть пентабайты посылай


 
Jolik   (2004-08-05 16:17) [5]

Спасибо всем...

То Rouse_: не нашел в сети примеров работы с каллбак функциями на overlapped WSA.... Может кините примерчик или ссылку. Или там все также как и с файлами?

То Anatoly Podgoretsky: сомневаюсь что так...
допустим у меня 10 МБит сетка (это физически, реально значит около 6 МБит), если я буду лить блок за блоком со скорость, например, 100 МБит, когда-то этот праздник должен кончтиься. Так или нет?


 
Rouse_ ©   (2004-08-05 16:26) [6]

Вот пример отправки...

WSA_INFINITE            = INFINITE;

 _OVERLAPPED = record
   Internal: DWORD;
   InternalHigh: DWORD;
   Offset: DWORD;
   OffsetHigh: DWORD;
   hEvent: THandle;
 end;
 PWSAOverlapped  = ^_OVERLAPPED;
 LPWSAOVERLAPPED = PWSAOverlapped;

 WSABUF = packed record
   len: U_LONG;  { the length of the buffer }
   buf: PChar; { the pointer to the buffer }
 end {WSABUF};
 PWSABUF = ^WSABUF;
 LPWSABUF = PWSABUF;

 LPWSAOVERLAPPED_COMPLETION_ROUTINE =
   procedure(const dwError, cbTransferred: DWORD;
   const lpOverlapped: LPWSAOVERLAPPED;
   const dwFlags: DWORD); stdcall;

 function WSASend(s: TSocket; lpBuffers: LPWSABUF; dwBufferCount: DWORD;
   var lpNumberOfBytesSent: DWORD; dwFlags: DWORD;
   lpOverlapped: LPWSAOVERLAPPED;
   lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE): Integer;
   stdcall; external "ws2_32.dll";

 function WSACreateEvent: WSAEVENT; stdcall; external "ws2_32.dll";

 function WSAWaitForMultipleEvents(cEvents: DWORD; lphEvents: PWSAEVENT;
   fWaitAll: LongBool; dwTimeout: DWORD; fAlertable: LongBool): DWORD;
   stdcall; external "ws2_32.dll";

 function WSACloseEvent(hEvent: WSAEVENT): WordBool;
   stdcall; external "ws2_32.dll";

....

procedure TGSClientSocketItem.DoWrite;

 procedure SocketWrite(const ASocket: TGSClientSocketItem); stdcall;

   procedure Complete(const dwError, cbTransferred: DWORD;
     const lpOverlapped: LPWSAOVERLAPPED;
     const dwFlags: DWORD); stdcall;
   begin
     if dwError <> 0 then
       PostMessage(lpOverlapped.hEvent, SOCKET_NOTIFY_MSG, WSAGetLastError, FD_ERROR);
   end;

 var
   Err: Integer;
   Overlapped: _OVERLAPPED;
   Buffer: WSABUF;
   SndCount: DWORD;
 begin
   FillChar(Overlapped, SizeOf(_OVERLAPPED), #0);
   Overlapped.hEvent := ASocket.FServer.FHandle; // Для нотификации об ошибке
   Buffer.buf := Pointer(ASocket.FSendStream);
   Buffer.len := Length(ASocket.FSendStream);
   if WSASend(ASocket.FSocket, @Buffer, 1,
     SndCount, 0,  @Overlapped, @Complete) = SOCKET_ERROR then
   begin
     Err := WSAGetLastError;
     if Err <> ERROR_IO_PENDING then
     begin
       ASocket.FServer.Error(Err);
       ASocket.DelState(csWriting);
       Exit;
     end;
   end;
   ASocket.FEvent := WSACreateEvent;
   try
     Err := WSAWaitForMultipleEvents(1, @ASocket.FEvent,
       False, WSA_INFINITE, True);
     if Err = WAIT_IO_COMPLETION then
     begin
       SetLength(ASocket.FSendStream, 0);
       if Assigned(ASocket.FServer.FWrite) then
         ASocket.FServer.FWrite(ASocket.FServer, ASocket);
     end
     else
       ASocket.FServer.Error(WSAGetLastError);
   finally
     WSACloseEvent(ASocket.FEvent);
     ASocket.DelState(csWriting);
   end;
 end;

var
 ID,
 Thread: DWORD;
begin
 if Length(FSendStream) = 0 then
 begin
   AddState(csReadyWrite);
   Exit;
 end;
 AddState(csWriting);
 Thread := CreateThread(nil, 0, @SocketWrite, Self, 0, ID);
 if Thread = 0 then FServer.Error(GetLastError);
end;


 
Anatoly Podgoretsky ©   (2004-08-05 16:27) [7]

Jolik   (05.08.04 16:17) [5]
Не это труба, как нефтяная сколько нелей всегда можно еще.


 
Anatoly Podgoretsky ©   (2004-08-05 16:28) [8]

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


 
Rouse_ ©   (2004-08-05 16:31) [9]

Да, кстати, для передачи файлов лучше TransmitFile использовать...


 
Rouse_ ©   (2004-08-05 16:32) [10]

> [7] Anatoly Podgoretsky ©   (05.08.04 16:27)
Ограничения есть, но обычно такие объемы махом в буффер не посылают :)


 
Anatoly Podgoretsky ©   (2004-08-05 16:41) [11]

Rouse_ ©   (05.08.04 16:32) [10]
А зачем махом, кусками


 
Jolik   (2004-08-05 17:34) [12]

за сорцы спасибо - разберусь, надеюсь...

по поводу пентабайт - уверен если закрутить в цикле на шустрой машине отправку например 16 кб блока - очень быстро все буфера в стеке ИП переполнятся...


 
Григорьев Антон ©   (2004-08-08 07:51) [13]

Что-то похожее обсуждалось здесь: http://delphi84.valuehost.ru/cgi-bin/forum.pl?id=1090501569&n=4
Почитайте, может, найдёте что-то полезное.


 
Verg ©   (2004-08-08 10:03) [14]

A completion indication will occur, invoking the completion of a routine or setting of an event object, when the supplied buffer(s) have been consumed by the transport.

Вот и не понятно:
А какой смысл в применении overlapped с WSASend, если все равно мы тут же ждем, пока операция завершится, при том INFINITE?

То же самое делается простым блокирующим send.

Далее.


> Overlapped.hEvent := ASocket.FServer.FHandle; // Для нотификации
> об ошибке


Здесь должен быть создан WSAEVENT ф-цией WSACreateEvent, а никакой не HWND!
Иначе вообще всякий смысл в OVERLAPPED теряется.


>   ASocket.FEvent := WSACreateEvent;
>    try
>      Err := WSAWaitForMultipleEvents(1, @ASocket.FEvent,
>        False, WSA_INFINITE, True);
>      if Err = WAIT_IO_COMPLETION then
>      begin
>        SetLength(ASocket.FSendStream, 0);
>        if Assigned(ASocket.FServer.FWrite) then
>          ASocket.FServer.FWrite(ASocket.FServer, ASocket);
>      end
>      else


Хм. Создаем какой-то event, который никогда ни кем не будет взведен, просто для того, чтобы дождаться IO completion в режиме alertable....

Если уж и ждать, то здесь ждать-то нужно как раз тот самый Overlapped.hEvent !!!

Вот и получилось масло маслянное: и IO Completion И Overlapped применен одновременно, но работает только IO Completion, т.к. Overlapped приеменен просто не-вер-но.

Я извиняюсь, но что-то тут напарено не по-детски.....


 
Verg ©   (2004-08-08 11:08) [15]


> [2] Jolik   (05.08.04 14:51)
> Я тк понимаю:
> send на асинхронном сокете может вернуть WSAEWOULDBLOCK
> - это значит, я сейчас ниче передавать не буду, а передам
> когда у меня будет время. При этом буфер с данными переданный
> в send копируется в системные буфера АйПи стека и передается
> когда появится возможность. Т.е. для программиста это все
> равно что полностью передано.


Не совсем так.
Если send вернул WSAEWOULDBLOCK, то это значит, что транспорт не в состоянии принять (скопировать) от тебя в свой передающий буфер ни одного байта вообще. Но как только у транспорта появится место в передающем буфере, тебя известят. Способов извещения существует по большому счету три:
- оконным сообщением FD_WRITE (WSAAsyncSelect)
- Установкой event-а (WSAEventSelect) во взведенное состояние
- Установкой дескриптора (FD_ISSET) в состояние готовности при вызове select и указании дескриптора (FD_SET) сокета в множестве writefds

Извещение о появлении места в передающем буфере выдается ТОЛЬКО после возникновения ошибки WSAEWOULDBLOCK при обращении send*** или WSASend***, а так же после успешного установления исходящего (клиентского) соединения.

Вопрос о том при появлении какого количества свободного места будет выдано указанное извещение остается мутным в рамках WSA. А в BSD этим параметром можно управлять (параметр SO_SNDLOWAT "Sends low watermark".)
SO_SNDLOWAT в winsock не поддерживается.


 
Rouse_ ©   (2004-08-08 20:56) [16]

> То же самое делается простым блокирующим send.
Да но у нас не блокирующий сокет...

> Здесь должен быть создан WSAEVENT ф-цией WSACreateEvent,
> а никакой не HWND!

Нет, используются процедуры завершения в которых параметр Overlapped.hEvent игнорируется (поэтому я его так нестандартно и использовал)

> Создаем какой-то event, который никогда ни кем не будет
> взведен, просто для того, чтобы дождаться IO completion
> в режиме


В противном случае процедура procedure Complete(const dwError, cbTransferred: DWORD; const lpOverlapped: LPWSAOVERLAPPED; попросту не отработает...

ЗЫ: Программирование в сетях Microsoft Windows Оланд, Джонс.
Там это все показано на примерах...


 
Rouse_ ©   (2004-08-08 21:01) [17]

> [14] Verg ©   (08.08.04 10:03)
В основном все эти замечания верны только в случае использования уведомлений о событии...
Но если использовать процедуры завершения (вышеупомянатая книга стр. 231) то можно заметить что код как раз таки верен...


 
Verg ©   (2004-08-08 21:26) [18]


> Нет, используются процедуры завершения в которых параметр
> Overlapped.hEvent игнорируется (поэтому я его так нестандартно
> и использовал)


Для чего же ты тогда его вообще использовал (overlapped)?


> PostMessage(lpOverlapped.hEvent, SOCKET_NOTIFY_MSG, WSAGetLastError,
> FD_ERROR);


Это зачем? :)) Здесь тебе что-то мешало  попосту

PostMessage(ASocket.FServer.FHandle, SOCKET_NOTIFY_MSG, WSAGetLastError,
FD_ERROR);

если уж так хочется...


> Да но у нас не блокирующий сокет...


Да-а? :)) Тогда зачем вообще весь это "сыр-бор"?


> В противном случае процедура procedure Complete(const dwError,
> cbTransferred: DWORD; const lpOverlapped: LPWSAOVERLAPPED;
> попросту не отработает...


С чего бы она не отработала? Мне это не понятно. Откуда такие "страхи"?


>  противном случае процедура procedure Complete(const dwError,
> cbTransferred: DWORD; const lpOverlapped: LPWSAOVERLAPPED;
> попросту не отработает...
>
> ЗЫ: Программирование в сетях Microsoft Windows Оланд, Джонс.
> Там это все показано на примерах...


Хочешь альтернативных примеров? Хорошо, будет время - будут примеры.
Просто смешно...


 
Rouse_ ©   (2004-08-08 21:41) [19]

> Для чего же ты тогда его вообще использовал
Нужно было использовать асинхронную модель, поэтому и использовал. Долго объяснять.

> Это зачем? :)) Здесь тебе что-то мешало  попосту
>
> PostMessage(ASocket.FServer.FHandle, SOCKET_NOTIFY_MSG,
> WSAGetLastError,
> FD_ERROR);

Мешало обычное AV :)

> С чего бы она не отработала? Мне это не понятно. Откуда
> такие "страхи"?

Цитирую:
"Сделав перекрытый запрос с процедурой завершения, вызывающий поток должен обязательно выполнить процедуру завершения по окончании запроса. Для этого нужно перевести поток в состояние ожидания...
Для перевода потока в состояние ожидания используйте WSAWaitForMultipleEvents. Если вызывающий поток всегда занят и не находится в состоянии ожидания, процедура завершения никогда не будет вызвана."


 
Verg ©   (2004-08-08 21:59) [20]


> Для перевода потока в состояние ожидания используйте WSAWaitForMultipleEvents.
> Если вызывающий поток всегда занят и не находится в состоянии
> ожидания, процедура завершения никогда не будет вызвана."


Ну и что? И для этого надо зводить фиктивные объекты, а в структуре overlapped вместо положенного объекта типа event подсовывать некие HWND?
Я уже говорил, что overlapped операции самодостаточниы и не требуют никаких искуственнопритянутыхзауши действий.
Если уж они вообще в таких случаях, в чем, собственно, НАИГЛУБОЧАЙИШИЕ сомнения, необходимы.

Либо книжки плохие, либо понимаешь ты их как-то превратно...

Как я не люблю в качестве аргумента цитаты из вумных книг.....

Ты сам-то как понимаешь, без кивков на "библию", что там творится?


 
Verg ©   (2004-08-08 22:13) [21]


> Мешало обычное AV :)


Хо, блин... Вот нифига себе! С какого места там AV может "светить"? К чему тут вообще тут вообще упоминание об AV, когда ты просто значение одной и той же переменной передаешь, фактически, через структуру Overlapped из одной процедуры в другую? При этом используешь совсем не для этого предназанченное место в Overlapped...


 
Rouse_ ©   (2004-08-09 09:17) [22]

Ну значит тогда вот тебе цитата из MSDN - это надеюсь вумная книга? :)

If the lpCompletionRoutine parameter is NULL, the hEvent parameter of lpOverlapped is signaled when the overlapped operation completes if it contains a valid event object handle. An application can use WSAWaitForMultipleEvents or WSAGetOverlappedResult to wait or poll on the event object.

If lpCompletionRoutine is not NULL, the hEvent parameter is ignored and can be used by the application to pass context information to the completion routine. A caller that passes a non-NULL lpCompletionRoutine and later calls WSAGetOverlappedResult for the same overlapped I/O request may not set the fWait parameter for that invocation of WSAGetOverlappedResult to TRUE. In this case the usage of the hEvent parameter is undefined, and attempting to wait on the hEvent parameter would produce unpredictable results.

> Ты сам-то как понимаешь, без кивков на "библию", что там
> творится?

Да уж не дурак, вроде соображаю :)

> Ну и что? И для этого надо зводить фиктивные объекты, а
> в структуре overlapped вместо положенного объекта типа event
> подсовывать некие HWND?

Читай выше выделено жирным...

> Хо, блин... Вот нифига себе! С какого места там AV может
> "светить"?

А вот с этим я не разобрался, но любое обращение в procedure Complete() к ASocket выводит к AV...


 
Rouse_ ©   (2004-08-09 09:20) [23]

Пардон первая часть цитаты не к месту, вот то что нужно (недокопировал текст)

The completion routine follows the same rules as stipulated for Windows file I/O completion routines. The completion routine will not be invoked until the thread is in an alertable wait state such as can occur when the function WSAWaitForMultipleEvents with the fAlertable parameter set to TRUE is invoked.


 
Rouse_ ©   (2004-08-09 09:23) [24]

ЗЫ: Кстати сия вумная книга была от Microsoft Press а не от "дядьки собрались выпили и написали :)"



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

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

Наверх





Память: 0.54 MB
Время: 0.031 c
8-1090516951
Pa5ha
2004-07-22 21:22
2004.10.17
Движок на D3D дайте плз


3-1095609402
map4ello
2004-09-19 19:56
2004.10.17
Access таблица и RecNo


1-1096362766
Drobu
2004-09-28 13:12
2004.10.17
Как отключить Debugger?


9-1087393359
Ezhik
2004-06-16 17:42
2004.10.17
GLScene


14-1096031082
vecna
2004-09-24 17:04
2004.10.17
Легализация оружия





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