Форум: "Сети";
Текущий архив: 2004.12.19;
Скачать: [xml.tar.bz2];
ВнизРазмер принимаемых данных Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.03 c