[我遵循了使用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
其余为零。
是什么给出的? 提前致谢!
答案 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 ...
}