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

时间:2010-05-22 06:40:27

标签: delphi winsock

[我遵循了使用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 

其余为零。

是什么给出的? 提前致谢!

2 个答案:

答案 0 :(得分:1)

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


<强>更新

看起来GetAcceptExSockaddrs的定义是错误的。我记得旧的Delphi版本包含了一个bug。正确的原型(取自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不是指向结构的指针,而是指向结构指针的指针。

答案 1 :(得分:0)

如果您使用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 ...
}