2011-03-03 123 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