基于Java Socket的简易聊天室实现步骤

橘子海
橘子海
发布时间:2026-10-15| 6人浏览过
原创

通过Java Socket和网络编程技术,可以构建支持多用户连接的聊天系统。本文将详细解析如何利用BIO(同步阻塞I/O)模型,结合多线程处理并发连接,实现包含用户名认证、群组广播及私聊功能的完整聊天室应用。

项目架构设计

聊天室采用C/S(客户端/服务器)架构,通信过程分为两个阶段:首先是身份认证,其次是即时通讯。为了确保系统的健壮性,建议先备份重要项目文件,防止代码冲突导致的数据丢失。

第1步:定义登录认证类 UserLogin

目的:建立预置的用户白名单,用于校验客户端提交的用户名是否合法。
核心逻辑:使用 HashSet 存储允许登录的用户标识(如 "111" 至 "555"),通过 contains() 方法快速判断。

import java.util.HashSet;
import java.util.Set;

public class UserLogin {
    // 初始化合法用户集合
    public static Set initUser() {
        Set set = new HashSet<>();
        set.add("111");
        set.add("222");
        set.add("333");
        set.add("444");
        set.add("555");
        return set;
    }

    // 验证登录状态
    public static boolean login(String username) {
        Set set = initUser();
        return set.contains(username);
    }
}

第2步:创建登录服务器 LoginServer

入口:TCP端口 6666。
动作:监听来自客户端的连接请求,读取用户名并调用认证方法。若认证成功,向客户端返回字符串 true,否则返回 false。
参数说明:需确保输入流与输出流的正确关闭及刷新,避免数据阻塞。

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class LoginServer {
    public static void main(String[] args) {
        int port = 6666;
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("登录服务器已经启动");
            while (true) {
                Socket socket = serverSocket.accept();
                InputStream inputStream = socket.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                
                String username = bufferedReader.readLine();
                OutputStream outputStream = socket.getOutputStream();
                PrintStream printStream = new PrintStream(outputStream);
                
                if (UserLogin.login(username)) {
                    System.out.println(username + "登录成功");
                    printStream.println("true");
                } else {
                    System.out.println(username + "登录失败");
                    printStream.println("false");
                }
                printStream.flush();
                // 注意:此处仅完成认证,未关闭socket以便后续连接到聊天服务器
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

第3步:创建聊天服务器 ChatServer

入口:TCP端口 9999。
动作:接收已认证用户的连接,将 <username, Socket> 存入全局 Map 中。为每个连接启动独立的线程 ChatThread 以处理该用户的消息收发。
关键状态:实时维护在线用户列表,作为消息转发的基础。

import com.socket.socketChatroom.bio.thread.ChatThread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class ChatServer {
    // 保存当前所有在线用户的Socket映射
    public static Map socketMap = new HashMap<>();

    public static void main(String[] args) {
        int port = 9999;
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("聊天服务器已经启动");
            while (true) {
                Socket socket = serverSocket.accept();
                InputStream inputStream = socket.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                
                String username = bufferedReader.readLine();
                System.out.println(username + "连接到聊天服务器");
                
                socketMap.put(username, socket);
                System.out.println(socketMap);
                
                // 为新连接创建独立线程进行处理
                new ChatThread(username, socket).start();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

第4步:实现客户端 Client 主程序

流程:先连接 LoginServer (port 6666) 进行验证;若返回 true,则建立与 ChatServer (port 9999) 的新连接。
并发处理:一旦建立聊天连接,立即启动发送线程 WriteThread 和接收线程 ReadThread,实现收发消息互不阻塞。

import com.socket.socketChatroom.bio.thread.ReadThread;
import com.socket.socketChatroom.bio.thread.WriteThread;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) {
        String ip = "127.0.0.1";
        int port = 6666; // 登录端口
        try {
            Socket client = new Socket(ip, port);
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入用户名");
            String username = scanner.nextLine();
            
            // 发送用户名到登录服务器
            OutputStream outputStream = client.getOutputStream();
            PrintStream printStream = new PrintStream(outputStream);
            printStream.println(username);
            printStream.flush();
            
            // 接收认证结果
            InputStream inputStream = client.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String state = bufferedReader.readLine();
            
            if (Boolean.parseBoolean(state)) {
                chat(username); // 登录成功,进入聊天流程
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void chat(String username) {
        try {
            String ip = "127.0.0.1";
            int port = 9999; // 聊天端口
            Socket socket = new Socket(ip, port);
            
            // 向聊天服务器发送用户名
            OutputStream outputStream = socket.getOutputStream();
            PrintStream printStream = new PrintStream(outputStream);
            printStream.println(username);
            printStream.flush();
            
            // 启动收发线程
            new ReadThread(socket).start();
            new WriteThread(socket).start();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

第5步:服务端消息分发线程 ChatThread

逻辑:循环读取客户端发来的消息。根据消息格式判断是单聊还是群聊:

  • 单聊:消息格式为 目标用户-内容,查找目标Socket并转发。
  • 群聊:遍历所有在线Socket(除自身外),广播消息。
import com.socket.socketChatroom.bio.server.ChatServer;
import java.io.*;
import java.net.Socket;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class ChatThread extends Thread {
    private final String username;
    private final Socket socket;

    public ChatThread(String username, Socket socket) {
        this.username = username;
        this.socket = socket;
    }

    @Override
    public void run() {
        while (true) {
            try {
                InputStream inputStream = socket.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                String message = bufferedReader.readLine();
                System.out.println(username + "说: " + message);
                
                Map socketMap = ChatServer.socketMap;
                Set usernameSet = new HashSet<>();
                for (Map.Entry map : socketMap.entrySet()) {
                    usernameSet.add(map.getKey());
                }
                
                // 解析单聊/群聊
                String[] values = message.split("-");
                if (values.length == 2 && usernameSet.contains(values[0])) { // 单聊
                    OutputStream out = socketMap.get(values[0]).getOutputStream();
                    PrintStream ps = new PrintStream(out);
                    ps.println(username + "说: " + values[1]);
                    ps.flush();
                } else { // 群聊
                    for (String targetUser : usernameSet) {
                        if (socket != socketMap.get(targetUser)) {
                            OutputStream out = socketMap.get(targetUser).getOutputStream();
                            PrintStream ps = new PrintStream(out);
                            ps.println(this.username + "说: " + message);
                            ps.flush();
                        }
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

第6步:客户端发送线程 WriteThread

作用:独立于主线程运行,负责监听用户键盘输入并通过Socket发送给服务器。
注意:输入格式需符合服务器解析规则。

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

public class WriteThread extends Thread {
    private final Socket socket;

    public WriteThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        while (true) {
            try {
                OutputStream outputStream = socket.getOutputStream();
                PrintStream printStream = new PrintStream(outputStream);
                Scanner scanner = new Scanner(System.in);
                System.out.println("请输入聊天内容: ");
                String message = scanner.nextLine();
                printStream.println(message);
                printStream.flush();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

第7步:客户端接收线程 ReadThread

作用:持续从服务器拉取消息并在控制台打印,确保用户可以随时看到他人发送的消息。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;

public class ReadThread extends Thread {
    private final Socket socket;

    public ReadThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        while (true) {
            try {
                InputStream inputStream = socket.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                String message = bufferedReader.readLine();
                System.out.println(message);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

项目结构展示

完整的工程目录应清晰分离服务器端、客户端及辅助线程类,方便管理。项目结构如图:

运行与测试流程

在IDEA中运行本示例时,需注意以下几点以确保服务正常开启:

  1. 首先依次启动 LoginServer 和 ChatServer。
  2. 由于需要模拟多个用户同时在线,需配置IDEA允许多个实例并行运行。
  3. 具体操作路径:进入 Run/Debug Configurations,勾选 Allow parallel run。

IDEA多实例配置界面如下:

8.1 登录环节测试

启动客户端后,控制台会提示输入用户名。输入预设的合法用户(如 "111")即可成功进入聊天系统。若输入非法用户则会被拒绝。登录交互过程见下图:

8.2 群聊测试

当多个用户同时在线时,直接发送消息内容(不带前缀),服务器将识别为群聊指令,并将消息分发给除发送者外的所有在线客户端。

8.3 单聊测试

在输入框中输入 目标用户名-消息内容 的格式(例如 222-hello),系统将识别为私聊,仅目标用户能收到该条消息。

以上就是基于Java Socket实现聊天室功能的详细内容,更多关于Java网络编程实战的资料请关注本站其它相关文章!
相关标签:

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

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 算法库。