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

Вниз

Размер принимаемых данных   Найти похожие ветки 

 
QuestionX ©   (2004-10-08 22:58) [0]

Скажите, а если я отправляю по сети данных:
send(Socket, Buf, BufCount, 0);
то существует ли вероятность того, что данные на стороне сервера будут получены по частям, т.е. получится, что recv(Socket, Buf, BufCount, 0) < BufCount ?


 
VMcL ©   (2004-10-08 23:23) [1]

>>QuestionX ©  (08.10.04 22:58)

>существует ли вероятность того, что данные на стороне сервера будут получены по частям

Да, причем почти наверняка так и будет, особенно если BufCount больше аппаратного и/или программного буфера передающих систем.


 
Verg ©   (2004-10-08 23:24) [2]


> то существует ли вероятность того, что данные на стороне
> сервера будут получены по частям, т.е. получится, что recv(Socket,
> Buf, BufCount, 0) < BufCount ?


Для TCP (SOCK_STREAM) это вообще нормальная (штатная) ситуация. Мало того еще и send(Socket, Buf, BufCount, 0) < BufCount - тоже запросто.

Способ как дробить на части (или объединять) поток передаваемых (принимаемых) данных определяет транспортный протокол. Это его право в замен на гарантию доставки данных в неискаженном виде в пределах соединения.

Почти с точностью до наоборот дело обстоит с SOCK_DGRAM или SOCK_RAW...


 
QuestionX ©   (2004-10-09 00:34) [3]

А как обеспечить на стороне клиента прием заданного количества байт и чтобы поток при этом спал до момента полного приема ?


 
Verg ©   (2004-10-09 00:54) [4]

var
 Buf : array[0.. BUFSIZE - 1] of byte; // BUFSIZE - "заданное кол-во байтов"
 recvd : integer;
 DataSize : integer;

 DataSize := 0;
 while DataSize < BUFSIZE do
 begin
   recvd := recv(Socket, Buf[DataSize], BUFSIZE-DataSize, 0);
   if recvd <= 0 then
   begin
      if recvd = 0 then
      begin
        // Connection Closed Gracefully
        break;
      end else
        raise Exception.Create(SysErrorMessage(WSAGetLastError));
   end;
   inc(DataSize, recvd);
 end;
 if recvd > 0 then
   // Buf содержит ровно BUFSIZE байтов переданных "собеседником"


 
QuestionX ©   (2004-10-09 01:04) [5]


> Verg ©   (09.10.04 00:54) [4]

Спасибо !


 
QuestionX ©   (2004-10-09 01:11) [6]

А не подскажете еще, как можно сделать тоже самое, но еще и контролировать возможность тайм-аута операции ?


 
Rouse_ ©   (2004-10-09 01:37) [7]

> [6] QuestionX ©   (09.10.04 01:11)
функция select, последний параметр... (с учетом блокирующего состояния...)


 
QuestionX ©   (2004-10-09 02:17) [8]

Вот, написал:

procedure TClientThread.RequireBuffer(Buffer: Pointer; BufSize: Integer;
 TimeOut: Integer = -1);
var
 FDSet: TFDSet;
 TimeVal: TTimeVal;
 RecvBytes: Integer;
 ErrorCode: Integer;
begin
 repeat
   if TimeOut > 0 then
   begin
     FD_ZERO(FDSet);
     FD_SET(ClientSocket.SocketHandle, FDSet);
     TimeVal.tv_sec := 60;
     TimeVal.tv_usec := 0;
   end;
   if select(0, @FDSet, nil, @FDSet, @TimeVal) = SOCKET_ERROR then
   begin
     ErrorCode := WSAGetLastError;
     raise ESocketError.CreateResFmt(@sWindowsSocketError,
         [SysErrorMessage(ErrorCode), ErrorCode, "recv"]);
   end;
   if (ClientSocket.ReceiveLength = 0) or Terminated then
     raise ETerminated.Create("RequireBuffer");
   RecvBytes := ClientSocket.ReceiveBuf(PChar(Buffer)^, BufSize);
   if (RecvBytes = 0) or Terminated then
     raise ETerminated.Create("RequireBuffer");
   Dec(BufSize, RecvBytes);
   Inc(Cardinal(Buffer), RecvBytes);
 until BufSize <= 0;
end;


Есть замечания ?


 
Rouse_ ©   (2004-10-09 03:18) [9]

> [8] QuestionX ©   (09.10.04 02:17)
По ней ничего не видно, ибо:
if (ClientSocket.ReceiveLength = 0) - это непонятно откуда берется...
а также RecvBytes...

or Terminated - обычно в таких случаях лучше выставить в самом начале...


 
QuestionX ©   (2004-10-09 03:27) [10]


> if (ClientSocket.ReceiveLength = 0) - это непонятно откуда
> берется...

Это берется как проверка почему вышли из select - по таймауту или по пришествии данных

> а также RecvBytes...

А что RecvBytes ?

> or Terminated - обычно в таких случаях лучше выставить в
> самом начале...

select - операция продолжительная - могут в ее процессе и завершить.


 
Rouse_ ©   (2004-10-09 03:50) [11]

> [10] QuestionX ©   (09.10.04 03:27)
Не видно просто где у тебя инициализируются или обновляются эти переменные...

> select - операция продолжительная - могут в ее процессе
> и завершить.

Но перед ее вызовом ты должен проверить, а не хотят ли терминировать поток?


 
QuestionX ©   (2004-10-09 03:55) [12]


> Не видно просто где у тебя инициализируются или обновляются
> эти переменные...

ClientSocket - свойство объекта TClientThread, а RecvBytes как написано в процедуре так и работает...

> Но перед ее вызовом ты должен проверить, а не хотят ли терминировать
> поток?

Согласен.

А вот интересно, что будет если попытаютися закрыть приложение, пока поток ждет select ?


 
Rouse_ ©   (2004-10-09 04:07) [13]

> А вот интересно, что будет если попытаютися закрыть приложение,
> пока поток ждет select ?

В данном варинте (если использовать методы VCL) ничего не будет...
Выставится флаг Terminated и всего делов...


 
Rouse_ ©   (2004-10-09 04:12) [14]

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


 
Rouse_ ©   (2004-10-09 04:16) [15]

точнее WSAEFAULT кажется :)
WSAECONNREFUSED для асинхронного сокета вывалится...

Эх блин, забыл матчасть.... :((


 
QuestionX ©   (2004-10-09 04:32) [16]


> В данном варинте (если использовать методы VCL) ничего не
> будет...
> Выставится флаг Terminated и всего делов...

Ничего не будет - это значит приложение не закроется или что ?


 
Rouse_ ©   (2004-10-09 04:59) [17]

> Ничего не будет - это значит приложение не закроется или
> что ?

Закроется конечно, главному потоку на второстепенный в принципе плевать при закрытии, хотя конечно лучше завершать потоки по честному  ;)


 
QuestionX ©   (2004-10-09 05:11) [18]


> Закроется конечно, главному потоку на второстепенный в принципе
> плевать при закрытии, хотя конечно лучше завершать потоки
> по честному  ;)

А разве главный поток не будет ждать завершения второстепенных ?


 
Verg ©   (2004-10-09 14:57) [19]

Я уже че-то не понимаю. То ли ты через WinsockAPI работал, то вдруг, откуда ни возьмись, появляется ClientSocket....
При том, на сколько можно только догадываться, в режиме ctBlocking...
Для работы в этом режиме, special for этот компонент есть специальный класс. Вполне приемлимая надстройка над блокирующим режимом.
TWinSocketStream - там есть и таймауты и проч...


 
QuestionX ©   (2004-10-09 15:09) [20]


> Я уже че-то не понимаю. То ли ты через WinsockAPI работал,
> то вдруг, откуда ни возьмись, появляется ClientSocket....

Имеется сервер - ThreadBlocking, так вот то, о чем я говорю - это один из потоков этого сервера. Ну а у них есть это свойство - ClientSocket. TWinSockStream - спасибо, посмотрел, но там read опять таки не ждет всего буфера, так что все равно переписывать...



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

Текущий архив: 2004.12.19;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.037 c
1-1102155767
ньюбик
2004-12-04 13:22
2004.12.19
TStatusBar - пара простых вопросов.


1-1102032607
Garfunkel
2004-12-03 03:10
2004.12.19
Сворачивание в трей при загрузке Windows


3-1100863630
Irina :)
2004-11-19 14:27
2004.12.19
Восстановление базы


14-1101707365
TButton
2004-11-29 08:49
2004.12.19
LAN


4-1099824141
Леонид
2004-11-07 13:42
2004.12.19
Сигнал микрофона