![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
не доходит значение типа integer [D7, WinXP]
Dmitry_177 © (2007-04-28 22:14:00)Использую WinSock, протокол TCP, может ли быть такое что не доходит значение типа integer? Просто так то у меня все работает, но иногда, очень редко бывает что недоходит значение типа integer, причем как-то странно то что именно в одном месте..
Dmitry_177 (2007-05-03 10:05:00) [1]Попробовал вот так:
function KLRecv(s: TSocket; var Buf; len, flags: Integer): Integer;
var
PBuf: Pointer; // чтобы двигать ЭТОТ указатель
BytesNeed: Integer;
BytesRecv: Integer;
FDSet: TFDSet;
TimeOut: TimeVal;
begin
FD_ZERO(FDSet);
FD_SET(s, FDSet);
TimeOut.tv_sec := 60;
TimeOut.tv_usec := 0;
PBuf := @Buf;
BytesNeed := len;
while BytesNeed > 0 do
begin
if select(0, @FDSet, nil, nil, @TimeOut) > 0 then // чтобы не застопорился на recv
begin
BytesRecv := recv(s, PBuf^, BytesNeed, flags);
if BytesRecv > 0 then
begin
Dec(BytesNeed, BytesRecv);
Inc(DWORD(PBuf), BytesRecv);
end
else
begin
Result := SOCKET_ERROR; // это чтобы в самой программе не сверять размер полученных байтов, т.к. всеравно они не все пришли, мне проще сделать это как ошибка SOCKET_ERROR, хоть даже сколько то и было полученно байт..
Break;
Exit;
end;
end
else
begin
Result := SOCKET_ERROR; // тоже самое
Break;
Exit;
end;
end;
Result := len;
end;
и в самой программе:
if KLRecv(KLSock, iRecv, SizeOf(iRecv), 0) <> SOCKET_ERROR then
...
всеравно если посылаю 1 приходит 5, как я понимаю к значению прибавляется размер получаемых данных, т.к. integer 4 байта занимает вот они и прибавляются.. подскажите пожалуйста..
Dmitry_177 (2007-05-03 00:20:00) [2]как я понял всегда прибавляется на 4.. Наверно это из-за этого: Inc(DWORD(Buf), BytesRead);но эта же строка тоже нужна для того чтобы не в начало буфера записывались последующие вызовы recv.. Что можно с этим сделать?
Dmitry_177 (2007-05-03 00:06:00) [3]Потом чисто ради эксперимента послал "111", получил "115"
Dmitry_177 (2007-05-03 00:02:00) [4]Странно как-то.. Используя тот код который я привел выше, посылаю значение типа integer равное "1", получаю "5"
DVM (2007-05-02 18:07:00) [5]
> Dmitry_177 (02.05.07 17:49) [30]
я вот так делаю:
function THTTPInputThread.ReadData(ABuffer: TBuffer; BytesExpected: integer): integer;
const
MaxLen = 262144;
var
TotalBytesToRead, Found, TotalBytesRead, BytesToRead, BytesRead: integer;
Rfds: TFDSet;
TempBuff: array [0..Pred(MaxLen)] of Char;
begin
FD_ZERO(Rfds);
FD_SET(Sock, Rfds);
Found := select(Sock, @Rfds, nil, nil, @FTimeout);
if Found = 0 then
begin
// Select timed out
Result := -1;
exit;
end
else
if Found = SOCKET_ERROR then
begin
// Select error
Result := -1;
exit;
end;
TotalBytesToRead := 0;
if BytesExpected <> 0 then
begin
TotalBytesToRead := BytesExpected;
end
else
begin
if ioctlsocket(Sock, FIONREAD, TotalBytesToRead) = SOCKET_ERROR then
begin
// Cannot ioctl()
Result := -1;
exit;
end;
if TotalBytesToRead = 0 then
begin
SocketDisconnect();
Result := 0;
exit;
end;
end;
TotalBytesRead := 0;
repeat
if TotalBytesToRead > MaxLen then
BytesToRead := MaxLen
else
BytesToRead := TotalBytesToRead;
ZeroMemory(@TempBuff[0], MaxLen);
BytesRead := recv(Sock, TempBuff, BytesToRead, 0);
if BytesRead = SOCKET_ERROR then
begin
// Read error
SocketDisconnect();
Result := -1;
exit;
end
else
if BytesRead = 0 then
begin
SocketDisconnect();
Result := 0;
exit;
end
else
begin
if ABuffer.Size >= 2097152 then
begin
SocketDisconnect();
Result := -1;
exit;
end;
ABuffer.Append(@TempBuff[0], BytesRead);
TotalBytesRead := TotalBytesRead + BytesRead;
TotalBytesToRead := TotalBytesToRead - BytesRead;
end;
until TotalBytesToRead <= 0;
Result := TotalBytesRead;
end;
Dmitry_177 (2007-05-02 17:49:00) [6]Чтобы каждый раз не мучаться при каждой посылке или приеме информации, я думаю лучше написать функции с этим циклом и уже их использовать.. Вот например с recv:
function NewRecv(s: TSocket; var Buf; len, flags: Integer): Integer;
var
BytesNeed: Integer;
BytresWrite: Integer;
begin
BytesNeed := len;
while BytesNeed > 0 do
begin
BytesRead := recv(s, Buf, BytesNeed, flags);
if BytesRead = SOCKET_ERROR then
begin
Result := SOCKET_ERROR;
Break;
Exit;
end;
if BytesRead = 0 then
begin
Result := len - BytesNeed;
Break;
Exit;
end;
if BytesRead > 0 then
begin
Dec(BytesNeed, BytesRead);
Inc(DWORD(Buf), BytesRead);
end;
end;
Result := len;
end;
Правильно ли так будет?
Сергей М. (2007-05-02 17:25:00) [7]
> или надо по кускам?
Об этом тебе скажет результат вызова send(), точно так же как результат вызова recv() говорит тебе о том, все ли из запрошенного тобой к чтению фактически прочитано.
Dmitry_177 (2007-05-02 17:21:00) [8]а как посылать лучше структуру TSelectDataPacket?
send(KLSock, SelectDataPacket, SizeOf(SelectDataPacket), 0) или надо по кускам?
Сергей М. (2007-05-02 16:56:00) [9]var
buf: Pointer;
BytesNeed: Integer;
BytresRead: Integer;
MyData: TMyType; //TMyType м.б. и Integer, и TSelectDataPacket, и что угодно
..
buf := @MyData;
BytesNeed := SizeOf(MyData);
while BytesNeed > 0 do begin
BytesRead := recv(KLSock, buf^, Min(BytesNeed, SizeOf(buf));
if BytesRead >= 0 then begin
Dec(BytesNeed, BytesRead);
Inc(DWord(buf), BytesRead);
end else
..
end;
Dmitry_177 (2007-05-02 16:53:00) [10]я вот так придумал:
var
b: bool;
i: integer;
iRecv: integer;
RecvSize: integer;
Buffer: array of Byte;
begin
b := false;
i := 0;
SetLength(Buffer, SizeOf(iRecv));
while not b do
begin
RecvSize := recv(KLSock, Buffer[i], SizeOf(Buffer), 0);
if RecvSize = Socket_Error then
begin
Break;
Exit;
end;
if RecvSize <> SizeOf(Buffer) then
begin
Move(Buffer[i], iRecv, RecvSize);
i := i + RecvSize;
end
else
b := true;
end;
end;
Правильно ли так будет или можно как-то проще и лучше?
Dmitry_177 (2007-05-02 16:37:00) [11]мне не очень понятно вот что: вот был вызван recv(KLSock, Buffer, SizeOf(Buffer), 0), вернул он например 2, т.е. было получено 2 байта, как мне потом при вызове следующего recv записать в конец данных в буфере а не в начало, т.е. не на те которые уже были приняты? Вот так: recv(KLSock, Buffer[3], SizeOf(Buffer)-2, 0)? и как мне реализовать лучше этот цикл? и еще при следующих вызовах recv сколько задавать на получение байт(3 параметр)? так как я уже привел: SizeOf(Buffer)-2?
Сергей М. (2007-05-02 16:33:00) [12]
> Dmitry_177 (02.05.07 16:16) [22]
Ну пусть даже так.
А теперь представь, что буфер Buffer заполняется полученными в рез-те вызовов ф-ции recv данными - первый полученный байт помещается в Buffer[0], второй - в Buffer[1], третий - в Buffer[2], N-ный - в Buffer[N-1] ..
SpellCaster (2007-05-02 16:30:00) [13]Можно и так
var
i: integer
Buffer: array [1..sizeof(integer)] of Byte absolute i;
Dmitry_177 (2007-05-02 16:16:00) [14]Так?
var
i: integer
Buffer: array of Byte;
SetLength(Buffer, SizeOf(i));
Move(Buffer, i, SizeOf(i));
Сергей М. (2007-05-02 16:04:00) [15]
> Dmitry_177 (02.05.07 15:53) [19]
Забудь на время про recv.
Простейший тест на знания Паскаля:
Если у тебя есть, к примеру, есть 4 байта, то как получить из них Integer, если имеющиеся байты следуют в Intel-порядке - от младшего к старшему ?
Dmitry_177 (2007-05-02 16:03:00) [16]на сколько я понимаю, нужно считывать в какой-то буфер, а как его объявлять? и как потом из него считать тот же integer?
Dmitry_177 (2007-05-02 15:53:00) [17]а как тогда все это склеить? к примеру integer был принят двумя recv-ами, как его склеить в одно?
Сергей М. (2007-05-02 15:42:00) [18]
> вызывать заново recv?
Да.
> как тогда мне получить значение типа
Вызывать recv до тех пор, пока не будут получены все данные требуемого размера.
> из этих двух recv-ов
Почему двух ?
Если ты ожидаешь, скажем , SizeOf(Integer)=4 байта, то теоретически может потребоваться от одного до четырех вызовов recv.
DVM (2007-05-02 15:36:00) [19]recv не знает ничего о TSelectDatapacket - она байты принимает
DVM (2007-05-02 15:35:00) [20]
> а что тогда делать? вызывать заново recv?
во первых она говорит сколько байт реально прочитано, а во вторых в цикле вызывай пока не получишь все.