How to Get Local IP by SocketHandle?

I am developing chatroom application - use TServerSocket and TClientSocket to Send and Receive Text I Can get Socket.SocketHandle from computer that sent for me, but how to get local IP (or Computernetname) of that computer.

Upvotes: 0

Views: 2052

Answers (2)

James L.
James L.

Reputation: 9453

I have used this code successfully for many years. You must include WinSock in your uses list. I have two global variables:

var
  FWSAData: TWSAData;
  FWSAStarted: Integer;

I use the following code to initialize the WSA one time, to avoid the overhead of doing it with each call to a WinSock method.

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

finalization
  if FWSAStarted = 0 then
    WSACleanup;

A user can have more than one local IP address. The following code demonstrates how to get both the computer name (to get the IP address) and how to get all IP addresses, separated by semicolons using the WinSock API calls:

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;

Upvotes: 1

Remy Lebeau
Remy Lebeau

Reputation: 595320

TCustomWinSocket has RemoteAddress and RemoteHost properties to get the peer's IP and Hostname values, respectively. You do not need to use the SocketHandle property unless you want to call Winsock API functions directly, like getpeername() and getnameinfo().

Upvotes: 3

Related Questions