Delphi winsock为什么在分配InAddr.S_addr时sockaddr_in值会出现“乱码”

时间:2015-02-11 16:59:07

标签: delphi winsock

我找到了一个函数来测试远程PC上是否打开了特定的tcp端口。它似乎工作正常,但是当我为变量client.sin_addr.S_addr指定一个值时,其他值似乎被分配了乱码值,至少我没有期望看到像我看到的那样的值。 / p>

分配client.sin_addr.S_addr之前的客户记录值:

(2, 39173, ((#0, #0, #0, #0), (0, 0), 0), (#0, #0, #0, #0, #0, #0, #0, #0), 2, (#5, '™', #0, #0, #0, #0, #0, #0, #0, #0, #0, #0, #0, #0))

分配client.sin_addr.S_addr后的客户记录值:

(2, 39173, (('À', '¨', #10, 'h'), (43200, 26634), 1745529024), (#0, #0, #0, #0, #0, #0, #0, #0), 2, (#5, '™', 'À', '¨', #10, 'h', #0, #0, #0, #0, #0, #0, #0, #0))

请注意,1745529024是IP地址192.168.10.104的正确表示。

就我所见,该功能按预期工作。我只是不喜欢那些乱码。

这是正常的,我应该担心,还是只是忽略它?

function PortTCP_IsOpen(dwPort : Word; InetAddress : AnsiString) : boolean;
var
  client : sockaddr_in;
  sock   : Integer;

  GInitData: TWSAData;
  ret : Integer;
  res : integer;
  msg : string;
begin
  Result:=False;
  ZeroMemory(@client, SizeOf(client));

  ret := WSAStartup($0002, GInitData); //initiates use of the Winsock DLL
  if ret <> 0 then RaiseLastOSError;
  try
    client.sin_family      := AF_INET;  //Set the protocol to use , in this case (IPv4)
    client.sin_port        := htons(dwPort); //convert to TCP/IP network byte order (big-endian)
    // before value
    client.sin_addr.S_addr := inet_addr(PAnsiChar('192.168.10.104'));     //inet_addr(PAnsiChar(ansistring(GetIPFromHost(InetAddress))));  //convert to IN_ADDR  structure
    // after value
    sock  := socket(AF_INET, SOCK_STREAM, 0);    //creates a socket
    Result:= connect(sock, client, SizeOf(client)) = 0;  //establishes a connection to a specified socket
    if Result then
    begin
      if not closesocket(sock) = 0 then
      begin
        res := WSAGetLastError;
        msg := SysErrorMessage(res);
        raise Exception.CreateFmt('%s Code:%d',[msg, res]);
      end;
    end else
    begin
      res := WSAGetLastError;
      msg := SysErrorMessage(res);
      raise Exception.CreateFmt('%s Code:%d',[msg, res]);
    end;
  finally
    WSACleanup;
  end;
end;

2 个答案:

答案 0 :(得分:3)

这些字段被声明为保持Char值,因此调试器会以这种方式解释它们并尝试显示字符。当然,它们并不是真正的字符,但是调试器并不知道更好。

十进制值1745529024是十六进制0x680AA8C0。最重要的字节是0x68,当解释为ASCII字符时,它是小写的 h 。值0x0A是换行符,表示为Delphi字符文字#10。等等。

答案 1 :(得分:1)

这是一个变体记录,就像C联盟一样。这是:

type
  in_addr = record
    case integer of
      0: (S_un_b: SunB);
      1: (S_un_w: SunW);
      2: (S_addr: u_long);
  end;

因此,S_addr保存值1745529024,其他两个成员重叠在同一个内存中。在十六进制中,1745529024$680AA8C0

现在,SunB是什么?

type
  SunB = record
    s_b1, s_b2, s_b3, s_b4: u_char;
  end;

因此调试器将S_addr的四个字节解释为ANSI编码字符,因此您在调试器中看到的内容。在本地ANSI表中查找$68$0A$A8$C0,您将找到调试器向您显示的四个值。

同样适用于SunW

type
  SunW = record
    s_w1, s_w2: u_short;
  end;

构成$680AA8C0的两个字确实是$A8C0 = 43200$680A = 26634

总之,情况正常,无需担心。

相关问题