Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Apr : Re: Problem send/recv a string using winsock
| Subject: | Re: Problem send/recv a string using winsock |
| Posted by: | "Remy Lebeau (TeamB)" (no.spam@no.spam.com) |
| Date: | Mon, 10 Apr 2006 12:42:27 |
"Jean-Francois Goulet" <gouletje@vif.com> wrote in message
news:44383d4c$1@newsgroups.borland.com...
> I'm trying to send a string but I only receive part of the string.
That is because you are not taking into account that data blocks are
commonly split into multiple packets, or multiple blocks merged into a
single packet, during TCP transmissions. Your reading and writing code has
to be written handle three different scenerios - 1) reading/writing as many
bytes as you requested, 2) reading/writing fewer bytes than you requested,
and 3) reading more bytes then you expected.
> More concretely, that string is a path.
The contents of the string are irrelevant. The socket doesn't care what you
pass to it. Everything is arbitrary bytes to it.
> The problem is that the string is sent correctly (at least is seems like
it is)
It is likely not actually being sent correctly at all. Especially if the
string is long. You are not taking into account that the socket may not
accept all of the string data at one time, so you would have to loop the
writing until all bytes have been accepted by the socket.
> and when i'm trying to receive it using winsock's recv function i
> only get all the string besides the first character.
That is because you are not reading data correctly at all.
> Now, I suspect the problem is more due to the buffer i use when i call
recv.
The problem is that your entire code is incomplete in general. Use this
code instead:
--- sender ---
procedure SendSocketRaw(S: TSocket; var Buffer; BufLen: Integer);
var
Status, ErrCode: Integer;
PBuf: PByte;
begin
PBuf := PByte(Buffer);
while BufLen > 0 do
begin
Status := send(S, PBuf, BufLen, 0);
if Status < 1 then
begin
if Status = 0 then
raise Exception.Create('Disconnected by other party')
ErrCode := WSAGetLastError;
if ErrCode <> WSAEWOULDBLOCK then
raise ESocketException.CreateFmt('Error on send(): %d
%s', [ErrCode, SysErrorMessage(ErrCode)]);
Sleep(10);
end;
end;
end;
function SendSocketString(S: TSocket; const Str: String): Boolean;
var
Len: Integer;
begin
Result := False;
try
Len := Length(Str);
// Send data length
SendSocketRaw(S, @Len, sizeof(Len));
// Send datas
SendSocketRaw(S, Pointer(Str), Len);
Result := True;
except
on E: Exception do
Application.MessageBox(PChar(E.Message), 'LuaEdit', MB_OK or
MB_ICONERROR);
end;
end;
var
RemotePath: String;
begin
RemotePath := 'whatever';
SendSocketString(MySocket, RemotePath);
end;
--- receiver ---
procedure ReadSocketRaw(S: TSocket; var Buffer; BufLen: Integer);
var
Status, ErrCode: Integer;
PBuf: PByte;
begin
PBuf := PByte(Buffer);
while BufLen > 0 do
begin
Status := recv(S, PBuf, BufLen, 0);
if Status < 1 then
begin
if Status = 0 then
raise Exception.Create('Disconnected by other party')
ErrCode := WSAGetLastError;
if ErrCode <> WSAEWOULDBLOCK then
raise ESocketException.CreateFmt('Error on recv(): %d
%s', [ErrCode, SysErrorMessage(ErrCode)]);
Sleep(10);
end;
end;
end;
function ReadSocketString(S: TSocket; var Str: String): Boolean;
var
Len: Integer;
begin
Result := False;
Str := '';
try
// Receive data length
ReadSocketRaw(S, @Len, sizeof(Len));
// Recieve datas
SetLength(Str, Len);
ReadSocketRaw(S, Pointer(Str), Len);
except
on E: Exception do
Application.MessageBox(PChar(E.Message), 'LuaEdit', MB_OK or
MB_ICONERROR);
end;
end;
var
FileName: String;
begin
ReadSocketString(MySocket, FileName);
end;
Gambit
none