GetAcceptExSockaddrs 返回垃圾!有谁知道为什么?

发布于 2024-09-02 04:13:20 字数 2125 浏览 7 评论 0原文

[我已遵循使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

生寂 2024-09-09 04:13:20

您使用的 Delphi 版本是什么?在任何情况下,不需要对 GetAcceptExSockaddrs 及其参数使用自己的类型定义,请使用 WinSock.pas 单元中的定义;它们至少与您的 unicode Delphi 版本的定义不同。


已更新

看起来 GetAcceptExSockaddrs 的定义是错误的。我记得旧的 Delphi 版本在这里包含一个错误。正确的原型(取自Delphi 2009 WinSock.pas)是

procedure GetAcceptExSockaddrs(lpOutputBuffer: Pointer;
  dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength: DWORD;
  var LocalSockaddr: PSockAddr; var LocalSockaddrLength: Integer;
  var RemoteSockaddr: PSockAddr; var RemoteSockaddrLength: Integer); stdcall;

注意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

procedure GetAcceptExSockaddrs(lpOutputBuffer: Pointer;
  dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength: DWORD;
  var LocalSockaddr: PSockAddr; var LocalSockaddrLength: Integer;
  var RemoteSockaddr: PSockAddr; var RemoteSockaddrLength: Integer); stdcall;

Note that LocalSockaddr and RemoteSockaddr are not pointers to structures but pointers to pointers to structures.

孤城病女 2024-09-09 04:13:20

如果您使用 mingw 的 GetAcceptExSockaddrs 原型,也会发生同样的情况。它返回垃圾。

而是以与解析 AcceptEx 和 ConnectEx 相同的方式解析 GetAcceptExSockaddrs,即:

#define WSAID_GETACCEPTEXSOCKADDRS { 0xb5367df2,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92} }

GUID GuidGetAcceptSockAddrs = WSAID_GETACCEPTEXSOCKADDRS;
DWORD dwBytes;

if ( WSAIoctl( activeSock,
               SIO_GET_EXTENSION_FUNCTION_POINTER,
               &GuidGetAcceptSockAddrs,
               sizeof (GuidGetAcceptSockAddrs),
               &pfnGetAcceptSockAddrs,
               sizeof (pfnGetAcceptSockAddrs),
               &dwBytes,
               NULL,
               NULL ) == SOCKET_ERROR )
{
     ... error ...
}

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.:

#define WSAID_GETACCEPTEXSOCKADDRS { 0xb5367df2,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92} }

GUID GuidGetAcceptSockAddrs = WSAID_GETACCEPTEXSOCKADDRS;
DWORD dwBytes;

if ( WSAIoctl( activeSock,
               SIO_GET_EXTENSION_FUNCTION_POINTER,
               &GuidGetAcceptSockAddrs,
               sizeof (GuidGetAcceptSockAddrs),
               &pfnGetAcceptSockAddrs,
               sizeof (pfnGetAcceptSockAddrs),
               &dwBytes,
               NULL,
               NULL ) == SOCKET_ERROR )
{
     ... error ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文