GetAcceptExSockaddrs 返回垃圾!有谁知道为什么?
[我已遵循使用 Winsock.pas 的建议,但它仍然会写入垃圾 - 尽管 sin_family 字段已更改为新的垃圾值。]
你好,我正在尝试在 Delphi 中编写一个快速/肮脏的 echoserver,但是我 请注意,GetAcceptExSockaddrs 似乎只写入前 4 个 我传递给它的结构的字节。
program TCPEcho;
{$APPTYPE CONSOLE}
uses Windows, SysUtils, Winsock;
type INT = SmallInt;
const
BufDataSize = 8192;
BufAddrSize = SizeOf (TSockAddrIn) + 16;
var
WSAData : TWSAData;
ListenSock, AcceptSock : TSocket;
Addr, LocalAddr, RemoteAddr : TSockAddrIn;
LocalAddrSize, RemoteAddrSize : Integer;
Ov : OVERLAPPED;
Buf : array[1..BufDataSize + BufAddrSize * 2] of Byte;
BytesReceived : DWORD;
begin
FillChar (WSAData, SizeOf (WSAData), 0);
WSAStartup (2, WSAData);
ListenSock := ValidSocketCheck ('Socket', Socket (AF_INET, SOCK_STREAM, IPPROTO_TCP));
FillChar (Addr, SizeOf (Addr), 0);
Addr.sin_family := AF_INET;
Addr.sin_port := HToNS (1066);
Addr.sin_addr.s_addr := HToNL (INADDR_ANY);
SocketCheck ('bind', bind (ListenSock, Addr, SizeOf (Addr)));
SocketCheck ('Listen', Listen (ListenSock, 3));
FillChar (Ov, SizeOf (Ov), 0);
Ov.hEvent := HandleCheck ('CreateEvent', CreateEvent (nil, False, False, nil));
AcceptSock := ValidSocketCheck ('Socket', Socket (AF_INET, SOCK_STREAM, IPPROTO_TCP));
if AcceptEx (ListenSock, AcceptSock, @Buf, BufDataSize, BufAddrSize, BufAddrSize, BytesReceived, @Ov) then
WinCheck ('SetEvent', SetEvent (Ov.hEvent))
else
if GetLastError <> ERROR_IO_PENDING then
WinCheck ('AcceptEx', GetLastError);
if WaitForMultipleObjects (1, @Ov.hEvent, False, INFINITE) <> WAIT_OBJECT_0 then
raise Exception.Create ('WFMO');
GetAcceptExSockaddrs (@Buf, BufDataSize, BufAddrSize, BufAddrSize, LocalAddr, LocalAddrSize, RemoteAddr, RemoteAddrSize);
WriteLn (RemoteAddr.sin_family);
end.
因此,如果我运行此程序,请使用 Telnet 连接到它(在同一台计算机上, 连接到 localhost),然后键入一个键,WaitForMultipleObjects 将解除阻止并且 GetAcceptExSockaddrs 将运行。 但结果却是垃圾!
RemoteAddr.sin_family = 51618
RemoteAddr.sin_port = 64
其余的都是零。
什么给? 提前致谢!
[I've followed the suggestion to use Winsock.pas, but it still writes garbage -- although the sin_family field has changed to a new garbage value.]
Hello, I'm trying to write a quick/dirty echoserver in Delphi, but I
notice that GetAcceptExSockaddrs seems to be writing to only the first 4
bytes of the structure I pass it.
program TCPEcho;
{$APPTYPE CONSOLE}
uses Windows, SysUtils, Winsock;
type INT = SmallInt;
const
BufDataSize = 8192;
BufAddrSize = SizeOf (TSockAddrIn) + 16;
var
WSAData : TWSAData;
ListenSock, AcceptSock : TSocket;
Addr, LocalAddr, RemoteAddr : TSockAddrIn;
LocalAddrSize, RemoteAddrSize : Integer;
Ov : OVERLAPPED;
Buf : array[1..BufDataSize + BufAddrSize * 2] of Byte;
BytesReceived : DWORD;
begin
FillChar (WSAData, SizeOf (WSAData), 0);
WSAStartup (2, WSAData);
ListenSock := ValidSocketCheck ('Socket', Socket (AF_INET, SOCK_STREAM, IPPROTO_TCP));
FillChar (Addr, SizeOf (Addr), 0);
Addr.sin_family := AF_INET;
Addr.sin_port := HToNS (1066);
Addr.sin_addr.s_addr := HToNL (INADDR_ANY);
SocketCheck ('bind', bind (ListenSock, Addr, SizeOf (Addr)));
SocketCheck ('Listen', Listen (ListenSock, 3));
FillChar (Ov, SizeOf (Ov), 0);
Ov.hEvent := HandleCheck ('CreateEvent', CreateEvent (nil, False, False, nil));
AcceptSock := ValidSocketCheck ('Socket', Socket (AF_INET, SOCK_STREAM, IPPROTO_TCP));
if AcceptEx (ListenSock, AcceptSock, @Buf, BufDataSize, BufAddrSize, BufAddrSize, BytesReceived, @Ov) then
WinCheck ('SetEvent', SetEvent (Ov.hEvent))
else
if GetLastError <> ERROR_IO_PENDING then
WinCheck ('AcceptEx', GetLastError);
if WaitForMultipleObjects (1, @Ov.hEvent, False, INFINITE) <> WAIT_OBJECT_0 then
raise Exception.Create ('WFMO');
GetAcceptExSockaddrs (@Buf, BufDataSize, BufAddrSize, BufAddrSize, LocalAddr, LocalAddrSize, RemoteAddr, RemoteAddrSize);
WriteLn (RemoteAddr.sin_family);
end.
So if I run this, connect to it with Telnet (on same computer,
connecting to localhost) and then type a key, WaitForMultipleObjects
will unblock and GetAcceptExSockaddrs will run.
But the result is garbage!
RemoteAddr.sin_family = 51618
RemoteAddr.sin_port = 64
and the rest is zeroes.
What gives?
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您使用的 Delphi 版本是什么?在任何情况下,不需要对 GetAcceptExSockaddrs 及其参数使用自己的类型定义,请使用 WinSock.pas 单元中的定义;它们至少与您的 unicode Delphi 版本的定义不同。
已更新
看起来 GetAcceptExSockaddrs 的定义是错误的。我记得旧的 Delphi 版本在这里包含一个错误。正确的原型(取自Delphi 2009 WinSock.pas)是
注意LocalSockaddr 和RemoteSockaddr 不是指向结构体的指针,而是指向结构体指针的指针。
What Delphi version are you using? In any case where is no need to use your own type definitions for GetAcceptExSockaddrs and its arguments, use the definitions from WinSock.pas unit; they differ from yours definitions at least for unicode Delphi versions.
Updated
Looks like the definition of GetAcceptExSockaddrs is wrong. I remember old Delphi versions contained a bug here. The correct prototype (taken from Delphi 2009 WinSock.pas) is
Note that LocalSockaddr and RemoteSockaddr are not pointers to structures but pointers to pointers to structures.
如果您使用 mingw 的 GetAcceptExSockaddrs 原型,也会发生同样的情况。它返回垃圾。
而是以与解析 AcceptEx 和 ConnectEx 相同的方式解析 GetAcceptExSockaddrs,即:
Same happens if you use the GetAcceptExSockaddrs prototype from mingw. It returns garbage.
Instead resolve the GetAcceptExSockaddrs the same way you resolve AcceptEx and ConnectEx, i.e.: