2011-03-03 129 views
0

当我建立到服务器的套接字连接时,客户端和服务器都打开了套接字。它很容易知道什么是服务器端口(因为我用它来连接到服务器)。但我想在连接到服务器后发现连接的客户端端口。我在Delphi 2010应用程序中使用Wininet函数。Wininet客户端端口 - delphi 2010

伪代码:

1 - InternetOpen
2 - InternetConnect
3 - HttpOpenRequest中
4 - HttpSendRequestA
5 - 的InternetReadFile
6 - ?????? < ------如何获取客户端端口?

编辑:

我发现我应该INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO使用InternetQueryOption,但我不知道该怎么做。

回答

3

你对正确使用InternetQueryOption功能与INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO标志,这将返回一个INTERNET_DIAGNOSTIC_SOCKET_INFO Structure

typedef struct { 
    DWORD_PTR Socket; 
    DWORD  SourcePort; 
    DWORD  DestPort; 
    DWORD  Flags; 
} INTERNET_DIAGNOSTIC_SOCKET_INFO, * LPINTERNET_DIAGNOSTIC_SOCKET_INFO; 

这在德尔福这个样子的

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. 
+0

哇!你真的是规矩。感谢这个非常完整的解决方案。我一直在寻找关于wininet的优秀文档,到目前为止我还没有发现任何东西。你有没有好的文件? – 2011-03-04 13:07:17

+0

顺便说一句,我真的很喜欢你的博客。 – 2011-03-04 14:11:00