【问题标题】:How check internet connection using Winsock api?如何使用 Winsock api 检查互联网连接?
【发布时间】:2019-03-02 20:35:17
【问题描述】:

我在下面构建了这段代码(基于this 示例)以使用Winsock api 检查是否存在与互联网的连接并尝试向特定网站(google.com in我的情况)。

但是WSAGetLastError返回错误码:10051

如何解决这个问题?

program Project1;

uses
  Windows, SysUtils, WinSock;

function GetIPFromHostName(const HostName: string): string;
var
  WSAData: TWSAData;
  R: PHostEnt;
  A: TInAddr;
begin
  Result := '0.0.0.0';
  WSAStartup($101, WSAData);
  R := GetHostByName(PAnsiChar(AnsiString(HostName)));
  if Assigned(R) then
  begin
    A := PInAddr(R^.h_Addr_List^)^;
    Result := WinSock.inet_ntoa(A);
  end;
end;

function IsConnectedToInternet: Boolean;
var
  WSAData1: TWSAData;
  SockAddr1: TSockAddr;
  Socket1: TSocket;
begin
  Result := False;

  if WSAStartup(MAKEWORD(2, 2), WSAData1) <> 0 then
  begin
    Writeln('WinSock error');
    Exit;
  end;

  Socket1 := Socket(AF_INET, SOCK_STREAM, 0);
  if Socket1 = INVALID_SOCKET then
  begin
    Writeln('socket error');
    Exit;
  end;

  SockAddr1.sin_family := AF_INET;
  SockAddr1.sin_addr.S_addr := inet_addr(PAnsiChar(GetIPFromHostName('google.com')));
  SockAddr1.sin_port := htons(80);

  if Connect(Socket1, SockAddr1, SizeOf(SockAddr1)) <> 0 then
  begin
    Writeln('connection error #', WSAGetLastError);
    Exit;
  end;

  Result := True;

  if CloseSocket(Socket1) <> 0 then
    Writeln('error closing socket');
end;

begin
  IsConnectedToInternet;
  readln;

end.

【问题讨论】:

  • 一方面,Google 将此类事情视为拒绝服务攻击,并会在短时间内阻止您。也许这是你的问题?无论如何,这不是检查 Internet 连接的正确方法。 Winsock 不是解决方案,还有其他特定于 Windows 的 API 用于获取有关 Internet 状态更改的通知,例如 iOS 和 Android 上存在的那些。
  • @AllenDrennan 实际上,连接到 Internet 服务器正是确定 Internet 连接是否可用的最佳方法。网络可能很复杂,并且可以通过许多不同的方式获得 Internet 连接。您提到的那些其他 API 并不总是准确/可靠。
  • 也许最好尝试连接到您想要/需要连接的实际服务器。我认为有成千上万的应用程序会在 Google 关闭后突然拒绝运行,即使它们根本不需要 Google。

标签: sockets delphi winsock delphi-10-seattle


【解决方案1】:

编译器警告您的错误,在您填写 in_addrsockaddr_in 的行上:

W1044 字符串到 PAnsiChar 的可疑类型转换

inet_addr 需要一个 ANSI 字符串。您将 unicode 字符串类型转换为 PAnsiChar 并因此传递了格式错误的字符串,导致 connect 无法找到目标。

替换

SockAddr1.sin_addr.S_addr := inet_addr(PAnsiChar(GetIPFromHostName('google.com')));

SockAddr1.sin_addr.S_addr :=
    inet_addr(PAnsiChar(AnsiString(GetIPFromHostName('google.com'))));


您可以使用为此目的设计的 API 之一,例如 InternetCheckConnectionInternetGetConnectedStateINetworkListManager 接口(Vista 及更高版本)。

例如

const
  FLAG_ICC_FORCE_CONNECTION = 1;
begin
  if not InternetCheckConnection('http://google.com', FLAG_ICC_FORCE_CONNECTION, 0) then
    RaiseLastOSError;

【讨论】:

  • 仅供参考,InternetCheckConnectionInternetGetConnectedState 因不可靠而臭名昭著。
  • @RemyLebeau,你是对的,+1。例如InternetGetConnectedState在我的测试中,只检测是否连接到网络适配器,对互联网信号一无所知。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-02
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 2012-02-18
  • 1970-01-01
相关资源
最近更新 更多