如何在Delphi中使用本机WinSock API简单地发送/接收整数值?

时间:2019-04-15 22:04:53

标签: sockets delphi winsock delphi-10-seattle

使用原生Winsock仅在一行中发送 / 接收的整数值的正确方法是什么,类似于下面的C ++代码?我尝试翻译此,但不知道是否正确。有谁可以帮助我吗?

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;

2 个答案:

答案 0 :(得分:3)

您使用:

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

send()的第二个参数是无类型的const参数,这意味着您可以传递具有地址的任何内容,但将整数强制转换为指针,然后对其取消引用是当然不正确

您可以简单地执行以下操作:

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

尽管如此,您可能必须使用 htonl()更改字节序:

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

您应该尝试两种选择,然后看看有什么用。其中之一是正确的。

您还应该使用 recv()以相同的方式传递整数。在 recv()调用之后,您可能必须使用 ntohl()(与 htonl()相反):

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

答案 1 :(得分:2)

send的呼叫是错误的。您必须为要发送的字节和字节数提供一个无类型的缓冲区。这里IntToStr绝对没有地方。

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

对于呼叫recv同样。

if recv(Sock, Width, SizeOf(Width), 0) <= 0 then Exit;

使用Ord()来获取Delphi枚举类型的序数值是习惯用法,因此Ord(MyEnum.element01)而不是Integer(MyEnum.element01),但是最终结果将完全相同。

您的代码无法在主机字节序和网络字节序之间转换。但是,C ++代码也没有。