Wininet客户端端口 - delphi 2010

时间:2011-03-03 22:05:00

标签: delphi sockets delphi-2010 wininet

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

的伪代码:

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

编辑:

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

1 个答案:

答案 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.