0

0

Java初学者项目实战:实现简单的网络聊天室应用

P粉602998670

P粉602998670

发布时间:2026-01-22 10:08:02

|

352人浏览过

|

来源于php中文网

原创

Java TCP聊天室需为每个客户端创建独立线程处理通信,服务端用ServerSocket.accept()接收连接后启动新线程,维护独立BufferedReader/PrintWriter,广播消息时遍历clients列表并flush;客户端异常断开需捕获IOException并清理资源。

java初学者项目实战:实现简单的网络聊天室应用

Java中用ServerSocket和Socket实现基础TCP聊天室

单线程的ServerSocket只能处理一个客户端,实际聊天室必须支持并发。核心是为每个连接启动独立线程,用Socket收发文本消息。注意:Java 8+ 可用ExecutorService替代裸线程,但初学者先理解线程模型更稳妥。

常见错误现象:IOException: Connection reset by peer——客户端异常关闭(比如直接关窗口)而服务端还在读,没做try-catch;或客户端写完没调flush(),服务端readLine()一直阻塞。

  • 服务端监听固定端口(如8080),accept()后立即交给新线程处理
  • 每个客户端线程维护自己的BufferedReaderPrintWriter,别共用
  • 消息广播时,遍历所有存活的PrintWriter逐个println()flush()
  • 客户端断开需在catch中清理对应输出流,并从全局列表移除
public class ChatServer {
    private static final List clients = new ArrayList<>();
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8080);
        System.out.println("Chat server started on port 8080");
        while (true) {
            Socket client = server.accept();
            new Thread(() -> handleClient(client)).start();
        }
    }
    private static void handleClient(Socket socket) {
        try (BufferedReader in = new BufferedReader(
                 new InputStreamReader(socket.getInputStream()));
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
            synchronized (clients) {
                clients.add(out);
            }
            String msg;
            while ((msg = in.readLine()) != null) {
                System.out.println("Received: " + msg);
                // 广播给其他所有人
                synchronized (clients) {
                    for (PrintWriter writer : clients) {
                        if (writer != out) { // 不回显给自己
                            writer.println(msg);
                            writer.flush();
                        }
                    }
                }
            }
        } catch (IOException e) {
            System.out.println("Client disconnected: " + e.getMessage());
        } finally {
            synchronized (clients) {
                clients.removeIf(writer -> writer.checkError());
            }
        }
    }
}

客户端用Swing写界面时避免Swing线程安全问题

Swing组件不是线程安全的,所有UI更新(如JTextArea.append())必须在事件调度线程(EDT)中执行。如果在Socket读取线程里直接调textArea.append(),可能卡死或抛IllegalStateException

使用场景:用户输入框(JTextField)回车发送、接收消息实时显示、连接状态提示。

立即学习Java免费学习笔记(深入)”;

  • 发送消息走ActionListener,天然在EDT中,可直接操作Socket输出流
  • 接收消息必须用SwingUtilities.invokeLater()包装UI更新逻辑
  • 连接失败或断开要弹出JOptionPane,也必须在EDT中调用
  • 不要在EDT中做socket.getInputStream().readLine()这种阻塞操作,会冻结整个界面

为什么不用UDP而坚持用TCP实现聊天室

初学者容易被“UDP更快”误导,但聊天室要求消息不丢、不错序、不重复。DatagramSocket发包无确认、无重传、无顺序保证,一次send()可能根本没到对方,或乱序到达,或重复送达——这会导致“消息消失”“别人说话顺序错乱”“同一句话刷屏两次”等不可接受的问题。

Sitekick
Sitekick

一个AI登陆页面自动构建器

下载

性能影响:TCP三次握手建立连接稍慢,但聊天室是长连接,只在登录时发生一次;后续消息吞吐量对局域网或普通宽带完全够用。真正瓶颈在广播逻辑和IO阻塞,不在协议本身。

  • 用TCP能直接依赖操作系统内核保证可靠交付,代码逻辑干净
  • 若强行用UDP,得自己实现序列号、ACK、重传、去重——这已超出初学者项目范围
  • Wireshark抓包验证:TCP会自动分段/重组,应用层看到的仍是完整行;UDP包超过MTU会被IP层分片,丢一片整条消息就废

调试时常见的连接拒绝与超时错误

Connection refused基本等于服务端根本没运行,或端口不对;Connection timed out通常是防火墙拦截、服务端绑定localhost导致外部连不上,或客户端填了错误IP。

关键检查点:

  • 服务端new ServerSocket(8080)是否成功?加System.out.println("Server bound")确认
  • 客户端连接地址是否写成"127.0.0.1"(本机)或真实局域网IP(跨设备测试)?别用"localhost"——某些系统解析异常
  • Windows/macOS防火墙是否放行java进程的入站连接?临时关闭防火墙测试
  • IDE运行服务端后,终端再起一个telnet 127.0.0.1 8080,能连上说明服务端OK,问题在客户端代码

多客户端测试时,别用同一个端口起多个服务端实例——BindException会明确告诉你端口已被占用。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

842

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

742

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

739

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

399

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

431

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16926

2023.08.03

Golang 性能分析与pprof调优实战
Golang 性能分析与pprof调优实战

本专题系统讲解 Golang 应用的性能分析与调优方法,重点覆盖 pprof 的使用方式,包括 CPU、内存、阻塞与 goroutine 分析,火焰图解读,常见性能瓶颈定位思路,以及在真实项目中进行针对性优化的实践技巧。通过案例讲解,帮助开发者掌握 用数据驱动的方式持续提升 Go 程序性能与稳定性。

1

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.7万人学习

C# 教程
C# 教程

共94课时 | 7.3万人学习

Java 教程
Java 教程

共578课时 | 49.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号