Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Apr : Re: Problem send/recv a string using winsock

www.cryer.info
Managed Newsgroup Archive

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

Replies:

none

In response to:

www.cryer.info
Managed Newsgroup Archive