Delphi winsock 为什么在分配 InAddr.S_addr 时 sockaddr_in 值得到 "garbled"
Delphi winsock why does sockaddr_in values get "garbled" when assigning InAddr.S_addr
我找到了一个函数来测试远程 PC 上的特定 tcp 端口是否打开。它似乎工作正常,但是当我为变量赋值时 client.sin_addr.S_addr
其他值似乎被分配了乱码,至少我没想到会看到像我看到的那样的值。
分配前的客户记录值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([=16=]02, 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;
这些字段被声明为持有 Char
值,因此调试器以这种方式解释它们并尝试显示字符。当然,它们并不是真正的字符,但调试器并不知道更好。
十进制值1745529024十六进制为0x680AA8C0。最高有效字节是 0x68,当解释为 ASCII 字符时,它是小写 h。值 0x0A 是换行符,表示为 Delphi 字符文字 #10
。等等。
这是一个变体记录,就像一个 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
是 0AA8C0
.
现在,SunB
是什么?
type
SunB = record
s_b1, s_b2, s_b3, s_b4: u_char;
end;
因此调试器将 S_addr
的四个字节解释为 ANSI 编码字符,因此您在调试器中看到的是。在本地 ANSI table 中查找 </code>、<code>[=20=]A
、$A8
和 $C0
,您将找到调试器显示给您的四个值。
同样 SunW
即:
type
SunW = record
s_w1, s_w2: u_short;
end;
而组成0AA8C0
的两个词确实是$A8C0 = 43200
和0A = 26634
。
综上所述,情况正常,不用担心。
我找到了一个函数来测试远程 PC 上的特定 tcp 端口是否打开。它似乎工作正常,但是当我为变量赋值时 client.sin_addr.S_addr
其他值似乎被分配了乱码,至少我没想到会看到像我看到的那样的值。
分配前的客户记录值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([=16=]02, 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;
这些字段被声明为持有 Char
值,因此调试器以这种方式解释它们并尝试显示字符。当然,它们并不是真正的字符,但调试器并不知道更好。
十进制值1745529024十六进制为0x680AA8C0。最高有效字节是 0x68,当解释为 ASCII 字符时,它是小写 h。值 0x0A 是换行符,表示为 Delphi 字符文字 #10
。等等。
这是一个变体记录,就像一个 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
是 0AA8C0
.
现在,SunB
是什么?
type
SunB = record
s_b1, s_b2, s_b3, s_b4: u_char;
end;
因此调试器将 S_addr
的四个字节解释为 ANSI 编码字符,因此您在调试器中看到的是。在本地 ANSI table 中查找 </code>、<code>[=20=]A
、$A8
和 $C0
,您将找到调试器显示给您的四个值。
同样 SunW
即:
type
SunW = record
s_w1, s_w2: u_short;
end;
而组成0AA8C0
的两个词确实是$A8C0 = 43200
和0A = 26634
。
综上所述,情况正常,不用担心。