0

我正在开发聊天室应用程序 - 使用 TServerSocket 和 TClientSocket 发送和接收文本我可以从为我发送的计算机获取 Socket.SocketHandle,但如何获取该计算机的本地 IP(或计算机网络名称)。

4

2 回答 2

2

TCustomWinSocket 具有RemoteAddressRemoteHost属性来分别获取对等方的 IP 和主机名值。您不需要使用该SocketHandle属性,除非您想直接调用 Winsock API 函数,例如getpeername()getnameinfo()

于 2013-05-02T16:01:04.420 回答
1

我已成功使用此代码多年。您必须包括WinSock在您的uses列表中。我有两个全局变量:

var
  FWSAData: TWSAData;
  FWSAStarted: Integer;

我使用以下代码进行WSA一次初始化,以避免每次调用 WinSock 方法时都会产生开销。

initialization
  FWSAStarted := WSAStartup(MakeLong(1, 1), FWSAData);

finalization
  if FWSAStarted = 0 then
    WSACleanup;

一个用户可以拥有多个本地 IP 地址。以下代码演示了如何获取计算机名称(以获取 IP 地址)以及如何获取所有 IP 地址,使用 WinSock API 调用以分号分隔:

function _GetComputerName : string;
var
  len: DWORD;
begin
  len := MAX_COMPUTERNAME_LENGTH + 1;
  SetLength (result, len);
  if not Windows.GetComputerName(PChar(result), len) then
    RaiseLastOSError;
  SetLength(result, len);
end;

function GetIPAddress: AnsiString;
var
  Host: AnsiString;
  IPs, i: Integer;
  HostEnt: PHostEnt;
  b1, b2, b3, b4: Byte;
begin
  if FWSAStarted <> 0 then
    raise Exception.Create('Unable to hook WINSOCK.  "GetIPAddress" failed.');

  Result  := '';
  Host    := AnsiString(_GetComputerName);
  HostEnt := GetHostByName(PAnsiChar(Host));

  if Assigned(HostEnt) then
    with HostEnt^ do
      begin
        // the ip addresses occupy 4 bytes per address in sequence from the beginning
        // of the string, followed by the host name
        IPs := (Length(h_addr^) - Length(Host)) div 4;
        for i := 0 to IPs-1 do
        begin
          b1 := Byte(h_addr^[0+(4*i)]);
          b2 := Byte(h_addr^[1+(4*i)]);
          b3 := Byte(h_addr^[2+(4*i)]);
          b4 := Byte(h_addr^[3+(4*i)]);
          Result := Result + AnsiStrings.Format(';%u.%u.%u.%u', [b1, b2, b3, b4]);
        end;
        System.Delete(Result, 1, 1); // delete the first semicolon
      end;
end;
于 2013-05-02T16:19:18.963 回答