Wininet 客户端端口 - delphi 2010

Posted

技术标签:

【中文标题】Wininet 客户端端口 - delphi 2010【英文标题】:Wininet client port - delphi 2010 【发布时间】:2011-03-03 22:05:00 【问题描述】:

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

伪代码:

1 - 互联网开放 2 - 互联网连接 3 - HttpOpenRequest 4 - HttpSendRequestA 5 - InternetReadFile 6 - ??????

已编辑:

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

【问题讨论】:

【参考方案1】:

关于使用带有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.

【讨论】:

哇!!你真的很规则。感谢这个非常完整的解决方案。我一直在寻找有关 wininet 的好文档,但到目前为止我一无所获。你有什么好的文件吗? 顺便说一句,我真的很喜欢你的博客。

以上是关于Wininet 客户端端口 - delphi 2010的主要内容,如果未能解决你的问题,请参考以下文章

Delphi - 使用 Wininet 下载文件?

Delphi - 需要 XE2 代码到 Delphi7。使用wininet下载文件

delphi中的动态数组和wininet?

WinInet 帖子的简单包装函数(在 Delphi 中)

Delphi用WinInet用用户名和密码下载文件

Delphi WinAPI InternetGetConnectedState(wininet.h)