如何通过SocketHandle获取本地IP?

时间:2013-05-02 15:53:00

标签: delphi client-server handle

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

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分: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;