Java Socket实现局域网聊天的核心原理与代码解析

Mia
Mia
发布时间:2026-10-15| 5人浏览过
原创

利用Java Socket技术构建局域网聊天程序,涉及服务端等待连接、客户端发起请求以及双方独立的数据收发线程。通过ServerSocket绑定端口建立会话,并使用BufferedReader和BufferedWriter封装字节流实现字符交换,确保消息实时同步。

架构设计与运行环境

Socket通信的核心在于建立长连接后的双向数据传输。本示例采用经典的C/S(客户端/服务器)模式,具体逻辑如下:

  • 服务端 (RunServer):启动后监听特定端口(如 8888),阻塞等待客户端连接。连接建立后,单独开启一个读取线程接收来自客户端的消息。
  • 客户端 (RunClient):通过IP地址连接服务器。成功后,开启一个写入线程向服务器发送消息。同时为了保持服务端不堵塞,通常也需要在服务器端或客户端配合处理并发。
  • 并发模型:题目要求“可以同时发送消息”,因此在实际应用中,接收和发送应分别由不同的Thread对象管理。本示例展示了基本的流式数据读写,实际生产环境需更完善的异常处理和断开检测。

第1步:搭建服务端监听与接收

服务端的主要任务是创建服务套接字并接管已建立的连接通道。

  1. 初始化端口:使用 ServerSocket(8888) 绑定本地端口。
  2. 等待连接:调用 serverSocekt.accept() 方法,该方法会阻塞当前线程直到有客户端接入。
  3. 数据流配置:获取连接对象的输入流,将其包装为 InputStreamReader 和 BufferedReader 以支持按行读取文本。
package com.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class RunServer {
    // 全局变量记录当前连接的对象
    public static Socket socket = null;

    /**
     * 建立服务器被动连接并开启接收循环
     */
    public void startServer() throws IOException {
        // 1. 创建服务套接字,监听8888端口
        ServerSocket serverSocekt = new ServerSocket(8888);
        System.out.println("服务器启动,等待连接...");

        // 注:此处原逻辑将接收线程的实例化放在accept之前,
        // 但标准流程通常是先 accept 拿到 socket 再处理。
        // 原代码结构中 rc 未直接使用,主要依赖主线程进行读取。

        // 2. 阻塞等待客户端连接
        RunServer.socket = serverSocekt.accept();
        System.out.println("客户端已连接");

        // 3. 配置输入流
        InputStream is = socket.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);

        String str = null;
        // 4. 循环读取消息
        while ((str = br.readLine()) != null) {
            System.out.print("输出信息:" + str);
        }

        // 5. 资源清理
        socket.shutdownInput();
        serverSocekt.close();
    }
}

第2步:编写客户端连接与发送逻辑

客户端负责主动发起TCP握手,并在连接建立后进行数据的持续推送。

  1. 用户交互选择:提供菜单选项,确定是主动连接指定IP,还是执行其他操作(本示例中仅保留了主动连接逻辑,因被动等待需复杂的状态机)。这里直接演示 startClient(String ip) 路径。
  2. 建立连接:使用 new Socket(ip, 8888) 发起请求。
  3. 写入流配置:通过 getOutputStream() 获取输出流,包装为 BufferedWriter。
package com.client;

import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;

/**
 * 客户端实现Runnable接口以便作为线程运行
 */
public class RunClient implements Runnable {

    @Override
    public void run() {
        Scanner input = new Scanner(System.in);
        // 简化逻辑:直接演示主动连接
        System.out.println("请输入服务器IP:");
        try {
            startClient(input.next());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 通过指定的IP与服务器建立连接并持续发送消息
     */
    public void startClient(String ip) throws Exception {
        // 1. 发起Socket连接
        Socket socket = new Socket(ip, 8888);
        System.out.println("连接建立成功...");

        // 2. 配置输出流
        OutputStream os = socket.getOutputStream();
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
        Scanner input = new Scanner(System.in);

        System.out.println("准备发送消息,输入任意内容回车发送,输入exit退出。");
        // 3. 循环写入
        while (true) {
            String msg = input.nextLine();
            if ("exit".equals(msg)) {
                break;
            }
            bw.write(msg);
            bw.newLine(); // 必须换行,否则服务器端的readLine无法捕获结束符
            bw.flush();   // 强制刷新缓冲区
        }
        
        // 资源关闭建议在实际代码中补充
        bw.close();
        socket.close();
    }
}

第3步:主入口启动与注意事项

在主程序入口实例化服务端并调用启动方法。此时服务端处于阻塞监听状态。

package com.start;
import com.server.RunServer;

public class Go {
    public static void main(String[] args) throws Exception {
        // 启动服务端
        RunServer rs = new RunServer();
        rs.startServer();
    }
}

在实际测试时,建议使用一台物理机和一台虚拟机,或者两个不同的终端窗口模拟不同节点。如果完全在同一台机器上,且未正确区分进程间的内存隔离,可能会因为回环接口(Loopback)的特性导致消息自发自收。

关键技术点总结

  • 缓冲区的必要性:直接使用 InputStream 读取二进制字节非常繁琐,通过 BufferedReader 可以方便地以行(Line)为单位处理文本协议消息。
  • flush() 的重要性:客户端写入时必须调用 bw.flush() 或设置自动刷新,否则数据会滞留缓冲区,服务器端将无法即时收到消息。
  • 并发处理的缺失提醒:上述基础代码主要侧重于流连接的打通。要实现“一边收一边发”的完美体验,客户端和服务端均需各自拥有独立的读线程和写线程,否则会因单线程阻塞在读取操作上而导致另一方向无响应。
以上就是Java Socket实现局域网聊天的详细内容,更多关于Java网络编程与Socket实战的资料请关注本站其它相关文章!
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。