当我建立到服务器的套接字连接时,客户端和服务器都打开了套接字。很容易知道什么是服务器端口(因为我用它连接到服务器)。但我想在连接到服务器后发现连接的客户端端口。我在Delphi 2010应用程序中使用Wininet函数。
的伪代码:
1 - InternetOpen
2 - InternetConnect
3 - HttpOpenRequest
4 - HttpSendRequestA
5 - InternetReadFile
6 - ?????? < ------如何获取客户端端口?
编辑:
我发现我应该在INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO中使用InternetQueryOption,但我不知道该怎么做。
答案 0 :(得分:3)
使用带有INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO
标记的InternetQueryOption
函数是正确的,这将返回INTERNET_DIAGNOSTIC_SOCKET_INFO Structure
typedef struct {
DWORD_PTR Socket;
DWORD SourcePort;
DWORD DestPort;
DWORD Flags;
} INTERNET_DIAGNOSTIC_SOCKET_INFO, * LPINTERNET_DIAGNOSTIC_SOCKET_INFO;
在Delphi中看起来像这样
PINTERNET_DIAGNOSTIC_SOCKET_INFO = ^TINTERNET_DIAGNOSTIC_SOCKET_INFO;
TINTERNET_DIAGNOSTIC_SOCKET_INFO= record
Socket : DWORD_PTR;
SourcePort : DWORD;
DestPort : DWORD;
Flags : DWORD;
end;
然后你可以编写一个函数来返回套接字信息
function GetSocketInfo(hInet: HINTERNET) : TINTERNET_DIAGNOSTIC_SOCKET_INFO;
var
lpdwBufferLength: DWORD;
begin
lpdwBufferLength:=SizeOf(TINTERNET_DIAGNOSTIC_SOCKET_INFO);
ZeroMemory(@Result,lpdwBufferLength);
if not InternetQueryOption(hInet, INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO, @Result, lpdwBufferLength) then
RaiseLastOSError;
end;
检查此示例应用以了解如何使用它。
{$APPTYPE CONSOLE}
uses
Windows,
WinInet,
SysUtils;
type
PINTERNET_DIAGNOSTIC_SOCKET_INFO = ^TINTERNET_DIAGNOSTIC_SOCKET_INFO;
TINTERNET_DIAGNOSTIC_SOCKET_INFO= record
Socket : DWORD_PTR;
SourcePort : DWORD;
DestPort : DWORD;
Flags : DWORD;
end;
const
INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO = Cardinal(67);
function GetSocketInfo(hInet: HINTERNET) : TINTERNET_DIAGNOSTIC_SOCKET_INFO;
var
lpdwBufferLength: DWORD;
begin
lpdwBufferLength:=SizeOf(TINTERNET_DIAGNOSTIC_SOCKET_INFO);
ZeroMemory(@Result,lpdwBufferLength);
if not InternetQueryOption(hInet, INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO, @Result, lpdwBufferLength) then
RaiseLastOSError;
end;
//this a dummy function to download a file, only to show the use of the INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO
procedure WinInet_HttpGet(const Url: string);
const
BuffSize = 1024*1024;
var
hInter : HINTERNET;
UrlHandle: HINTERNET;
BytesRead: DWORD;
Buffer : Pointer;
SocketInfo: TINTERNET_DIAGNOSTIC_SOCKET_INFO;
begin
hInter := InternetOpen('', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if Assigned(hInter) then
begin
GetMem(Buffer,BuffSize);
try
UrlHandle := InternetOpenUrl(hInter, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0);
if Assigned(UrlHandle) then
begin
//Get the info of the socket
SocketInfo:=GetSocketInfo(UrlHandle);
Writeln('Socket Info');
Writeln(Format('Source Port %d',[SocketInfo.SourcePort]));
Writeln(Format('Dest Port %d',[SocketInfo.DestPort]));
try
repeat
InternetReadFile(UrlHandle, Buffer, BuffSize, BytesRead);
if BytesRead>0 then
begin
//do your stuff
end;
until BytesRead = 0;
finally
InternetCloseHandle(UrlHandle);
end;
end;
finally
FreeMem(Buffer);
end;
InternetCloseHandle(hInter);
end
end;
begin
try
WinInet_HttpGet('http://msdn.microsoft.com/en-us/library/aa385096%28v=vs.85%29.aspx');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
readln;
end.