2013-05-02 58 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