杰瑞科技汇

Java客户端IP如何获取?

服务器端如何获取连接到它的客户端的 IP 地址?

Java客户端IP如何获取?-图1
(图片来源网络,侵删)

客户端自身的 IP 地址通常是已知的,因为它需要连接到服务器,但服务器端需要从 Socket 对象中获取客户端的连接信息。

核心方法

当服务器端通过 ServerSocketaccept() 方法接收到一个客户端连接后,会返回一个代表该连接的 Socket 对象,这个 Socket 对象包含了客户端的所有连接信息,包括 IP 地址和端口号。

获取客户端 IP 地址最常用的方法是:

socket.getInetAddress().getHostAddress();
  • socket:是服务器端接收客户端连接后返回的 Socket 对象。
  • getInetAddress():返回一个 InetAddress 对象,该对象封装了客户端的 IP 地址信息。
  • getHostAddress():将 InetAddress 对象转换为一个标准的 IP 地址字符串("192.168.1.100")。

还有一个方法是 getHostName(),它会尝试获取客户端的主机名,如果无法解析主机名,它可能会返回 IP 地址本身,或者抛出一个异常,通常我们更关心 IP 地址,getHostAddress() 更常用。

Java客户端IP如何获取?-图2
(图片来源网络,侵删)

完整代码示例

下面是一个完整的、可运行的 Echo 服务器和客户端示例,清晰地展示了服务器如何获取并显示客户端的 IP 地址。

服务器端代码 (Server.java)

这个服务器会接收来自客户端的连接,打印出客户端的 IP 地址和端口号,然后将客户端发回的消息原样返回。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
    private static final int PORT = 8888;
    public static void main(String[] args) {
        // 使用线程池来处理多个客户端连接
        ExecutorService threadPool = Executors.newCachedThreadPool();
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("服务器启动,监听端口 " + PORT + "...");
            while (true) {
                // accept() 方法会阻塞,直到有客户端连接
                Socket clientSocket = serverSocket.accept();
                // 获取客户端的 IP 地址和端口号
                InetAddress clientAddress = clientSocket.getInetAddress();
                String clientIp = clientAddress.getHostAddress();
                int clientPort = clientSocket.getPort();
                System.out.println("客户端已连接: IP = " + clientIp + ", 端口 = " + clientPort);
                // 为每个客户端连接创建一个任务,交给线程池处理
                threadPool.execute(() -> handleClient(clientSocket));
            }
        } catch (IOException e) {
            System.err.println("服务器异常: " + e.getMessage());
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }
    }
    /**
     * 处理单个客户端连接的线程任务
     * @param clientSocket 客户端的 Socket 对象
     */
    private static void handleClient(Socket clientSocket) {
        // 使用 try-with-resources 确保流被正确关闭
        try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
             PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {
            String inputLine;
            // 读取客户端发送的消息
            while ((inputLine = in.readLine()) != null) {
                System.out.println("来自 [" + clientSocket.getInetAddress().getHostAddress() + "] 的消息: " + inputLine);
                // 将消息回显给客户端
                out.println("服务器收到了你的消息: " + inputLine);
                // 如果客户端发送 "bye",则关闭连接
                if ("bye".equalsIgnoreCase(inputLine)) {
                    System.out.println("客户端 [" + clientSocket.getInetAddress().getHostAddress() + "] 请求断开连接。");
                    break;
                }
            }
        } catch (IOException e) {
            // 如果客户端异常断开,这里会捕获到异常
            System.err.println("处理客户端 [" + clientSocket.getInetAddress().getHostAddress() + "] 时发生异常: " + e.getMessage());
        } finally {
            // 确保关闭客户端 Socket
            try {
                clientSocket.close();
                System.out.println("与客户端 [" + clientSocket.getInetAddress().getHostAddress() + "] 的连接已关闭。");
            } catch (IOException e) {
                System.err.println("关闭客户端 Socket 时出错: " + e.getMessage());
            }
        }
    }
}

客户端代码 (Client.java)

这个客户端连接到服务器,发送消息,并接收服务器的响应。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
    private static final String SERVER_HOST = "localhost"; // 或服务器的实际IP地址
    private static final int SERVER_PORT = 8888;
    public static void main(String[] args) {
        // 客户端如何获取自己的IP地址?见下面的补充说明
        System.out.println("客户端启动...");
        try (
            // 1. 创建一个 Socket 并连接到服务器
            Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
            // 2. 获取输出流,用于向服务器发送数据
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            // 3. 获取输入流,用于读取服务器的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))
        ) {
            // 获取客户端本地的 IP 地址和端口
            InetAddress localAddress = socket.getLocalAddress();
            String localIp = localAddress.getHostAddress();
            int localPort = socket.getLocalPort();
            System.out.println("已连接到服务器,客户端本地信息: IP = " + localIp + ", 端口 = " + localPort);
            // 从控制台读取用户输入
            BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
            String userInput;
            System.out.println("请输入要发送的消息 (输入 'bye' 退出):");
            while ((userInput = stdIn.readLine()) != null) {
                // 发送消息到服务器
                out.println(userInput);
                // 如果用户输入 'bye',则退出循环
                if ("bye".equalsIgnoreCase(userInput)) {
                    break;
                }
                // 读取并打印服务器的响应
                String serverResponse = in.readLine();
                System.out.println("服务器响应: " + serverResponse);
                System.out.println("请输入要发送的消息 (输入 'bye' 退出):");
            }
        } catch (UnknownHostException e) {
            System.err.println("无法找到服务器: " + SERVER_HOST);
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("I/O Error: " + e.getMessage());
            e.printStackTrace();
        }
        System.out.println("客户端关闭。");
    }
}

如何运行

  1. 编译代码

    Java客户端IP如何获取?-图3
    (图片来源网络,侵删)
    javac Server.java Client.java
  2. 启动服务器

    java Server

    你会看到控制台输出:

    服务器启动,监听端口 8888...
  3. 启动客户端: 打开一个新的终端窗口,运行客户端:

    java Client

    客户端控制台会显示:

    客户端启动...
    已连接到服务器,客户端本地信息: IP = 127.0.0.1, 端口 = 54321
    请输入要发送消息 (输入 'bye' 退出):
  4. 交互

    • 在客户端输入 Hello,然后回车。
    • 服务器控制台会显示:
      客户端已连接: IP = 127.0.0.1, 端口 = 54321
      来自 [127.0.0.1] 的消息: Hello
    • 客户端控制台会显示:
      服务器响应: 服务器收到了你的消息: Hello
      请输入要发送消息 (输入 'bye' 退出):

补充说明:客户端如何获取自己的 IP 地址?

虽然你的主要问题是服务器获取客户端 IP,但了解客户端如何获取自己的 IP 也很重要。

客户端在成功连接到服务器后,可以通过其 Socket 对象获取自己的本地绑定信息。

Socket socket = new Socket("server_ip", server_port);
// 获取客户端自己的 IP 地址 (本地绑定的地址)
String myIp = socket.getLocalAddress().getHostAddress();
// 获取客户端自己的端口号 (本地绑定的端口)
int myPort = socket.getLocalPort();
System.out.println("我的IP地址是: " + myIp + ", 我的端口号是: " + myPort);
  • getLocalAddress():返回客户端套接字绑定到的本地地址。
  • getLocalPort():返回客户端套接字绑定到的本地端口。

注意:如果客户端没有显式绑定到一个特定的地址和端口(就像上面的例子一样),JVM 会自动选择一个可用的临时端口和默认的本地地址(通常是 0.0.0,代表所有可用的网络接口)。

场景 核心代码 说明
服务器获取客户端IP clientSocket.getInetAddress().getHostAddress() 这是最常用和最重要的方法。clientSocketServerSocket.accept() 返回的对象。
客户端获取自己IP clientSocket.getLocalAddress().getHostAddress() clientSocketnew Socket(...) 创建的对象,这获取的是客户端连接时绑定的本地地址。
获取主机名 socket.getInetAddress().getHostName() 尝试获取主机名,可能比 IP 地址更易读,但可能失败或较慢。

希望这个详细的解释和示例能帮助你完全理解在 Java Socket 编程中如何处理客户端 IP 地址。

分享:
扫描分享到社交APP
上一篇
下一篇