Search code examples
socketsdelphiwinsockdelphi-10-seattle

How make a simply send/receive of integer value using native WinSock api in Delphi?


What is the right way of send/receive a integer value using native winsock in only one line, similar to C++ code below? i'm tried translate this, but not know if is right. Can someone help me please?

C++:

enum MyEnum { element01, element02 };
int width;

int SendInt(SOCKET sock, int i)
{
   return Send(sock, (char *) &i, sizeof(i), 0);
}

if(SendInt(sock, MyEnum::element01) <= 0) return;
if(SendInt(sock, 0) <= 0) return;
if(recv(sock, (char *) &width, sizeof(width), 0) <= 0) return;

Delphi:

type
  MyEnum = (element01, element02);

var
 Width: Integer;

function SendInt(S: TSocket; I: Integer): Integer;
begin
  Result := send(S, PAnsiChar(I)^, Length(IntToStr(I)), 0);
end;

if SendInt(Sock, Integer(MyEnum.element01)) <= 0 then Exit;
if SendInt(Sock, 0) <= 0 then Exit;
if recv(Sock, PAnsiChar(Width)^, Length(IntToStr(Width)), 0) <= 0 then Exit;

Solution

  • You use:

    function SendInt(S: TSocket; I: Integer): Integer;
    begin
      Result := send(S, PAnsiChar(I)^, Length(IntToStr(I)), 0);
    end;
    

    The second parameter of send() is an untyped const parameter, meaning you can pass anything that has an address, but casting the integer to a pointer and then dereferencing it is certainly not correct.

    You can simply do this:

    begin
      Result := send(S, I, SizeOf(I), 0);
    end;
    

    Although, you may have to change the endianness using htonl():

    begin
      // I := htonl(I); ??
      Result := send(S, I, SizeOf(I), 0);
    end;
    

    You should try both alternatives and see what comes out of it. One of them is correct.

    You should also pass the integer the same way using recv(). You may have to use ntohl() (the opposite of htonl()) after a recv() call:

    function RecvInt(S: TSocket; var J: Integer): Integer;
    begin
      Result := recv(S, J, SizeOf(J), 0);
      // J := ntohl(J); ??
    end;