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

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

Размер принимаемых данных


QuestionX ©   (2004-10-08 22:58:00) 

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


QuestionX   (2004-10-09 15:09:00) [1]


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

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


Verg   (2004-10-09 14:57:00) [2]

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


QuestionX   (2004-10-09 05:11:00) [3]


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

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


Rouse_   (2004-10-09 04:59:00) [4]

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

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


QuestionX   (2004-10-09 04:32:00) [5]


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

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


Rouse_   (2004-10-09 04:16:00) [6]

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

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


Rouse_   (2004-10-09 04:12:00) [7]

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


Rouse_   (2004-10-09 04:07:00) [8]

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

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


QuestionX   (2004-10-09 03:55:00) [9]


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

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

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

Согласен.

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


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

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

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

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


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


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

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

> а также RecvBytes...

А что RecvBytes ?

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

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


Rouse_   (2004-10-09 03:18:00) [12]

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

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


QuestionX   (2004-10-09 02:17:00) [13]

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

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 01:37:00) [14]

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


QuestionX   (2004-10-09 01:11:00) [15]

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


QuestionX   (2004-10-09 01:04:00) [16]


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

Спасибо !


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

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 00:34:00) [18]

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


Verg   (2004-10-08 23:24:00) [19]


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


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

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

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


VMcL   (2004-10-08 23:23:00) [20]

>> QuestionX ©  (08.10.04 22:58)

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

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


Наверх

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