2013-05-02 75 views
0

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

+1

IPv4和/或IPv6? – mjn 2013-05-02 16:24:54

+0

我以为'ScktComp'已折旧并且不推荐? – 2013-05-02 16:38:24

+0

@JerryDodge:已经过时了,现在已经有一段时间了。但OP没有指定他使用的是哪个Delphi版本,所以我猜测他使用的是旧版本,其中这些组件尚未被弃用,特别是考虑到它们必须在现代Delphi版本中手动安装以便继续使用它们。 – 2013-05-03 03:17:30

回答

2

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

+0

太棒了!非常感谢! 我只有15岁,很想用Delphi创建一些应用程序。 我想我可以学习很多东西,谢谢! – 2013-05-03 00:26:37

1

我已经成功使用了这段代码很多年了。您必须在您的uses列表中包含WinSock。我有两个全局变量:

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; 
+0

我可能误解了你的问题。我以为你想知道如何获得你的应用程序运行的计算机的IP地址。看来您正在询问如何获取远程计算机的本地地址。此代码仅用于获取运行应用程序的计算机的本地IP。如果您正在为客户端和服务器编写应用程序,那么您可以在客户端应用程序中使用它... – 2013-05-02 21:25:05

+0

谢谢,但我认为它很长,只需使用RemoteAddress – 2013-05-03 00:35:04

+0

@JamesL .:使用'gethostbyname()'来检索本地IP并不是100%可靠的,因为它在某些配置中有一些隐藏的陷阱。您确实应该使用'GetAdaptersInfo()'或'GetAdaptersAddresses()',它们专门用于检索本地适配器信息(包括IP)。更不用说'gethostbyname()'只支持IPv4,但'GetAdaptersAddresses()'同时支持IPv4和IPv6。 – 2013-05-03 03:19:39