Java Socket实现简易多人聊天室传输聊天内容或文件

本文介绍了一个使用Java Socket实现的多人聊天室项目,包括文本聊天和文件传输功能。服务器端通过监听线程处理客户端连接,为每个客户端创建处理收发信的线程。客户端则有发送消息和接收消息的线程,通过标志位区分文本和文件传输。项目展示了如何通过Socket实现实时通信和文件交换。
摘要由CSDN通过智能技术生成

Java Socket实现简易多人聊天室传输聊天内容或文件

Java小练手项目:用Java Socket实现多人聊天室,聊天室功能包括传输聊天内容或者文件。相比于其它的聊天室,增加了传输文件的功能供参考。

模块拆解

分成服务端和客户端两部分来写

服务端包括监听线程和处理收发信线程:

  1. 创建监听线程,监听客户端的连接。将每个连接的客户端加入维护的列表,并为每个连接的客户端开启一个处理收发信的线程。
  2. 在每个客户端的收发信线程中,接收每个客户端发回的消息,并对其进行转发到相应接收的客户端上,以此实现多人聊天室。
  3. 添加处理传输文件的判断,通过在传输的字节数组中添加标志位来区分传输的是文本消息,还是文件。

客户端包括发送消息线程和接收消息线程:

  1. 发送消息线程,用来处理用户的输入信息,判断输入的是文本信息还是文件,并修改传输的字节数组标志位进行区分。最后将信息传输给服务器。
  2. 接收消息线程,用来处理服务器发回的信息,根据标志位判断输入的是文本信息还是文件,并做相应处理。如果是文本信息,则显示在控制台,如果是文件,则保存在指定目录下。

项目的目录结构如下所示

接下来,给出实际的代码进行分析

项目代码

服务器端

监听线程

package Server;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class MultiServer {
    public static void main(String[] args) {
        ServerSocket ss = null;
        Socket s = null;

        // 定义一个List列表来保存每个客户端,每新建一个客户端连接,就添加到List列表里。
        List<Socket> listSocket = new ArrayList<>();
        try {
            // 1. 创建ServerSocket类型的对象并提供端口号
            ss = new ServerSocket(9999);
            // 2. 等待客户端的连接请求,调用accept方法
            // 采用多线程的方式,允许多个用户请求连接。
            int i = 0;
            while (true) {
                System.out.println("等待客户端的连接请求...");
                s = ss.accept();
                listSocket.add(s);
                //sArr[i] = s;
                i++;
                System.out.printf("欢迎用户%d加入群聊!\n", i);
                System.out.printf("目前群聊中共有%d人\n", listSocket.size());
                InetAddress inetAddress = s.getInetAddress();
                System.out.println("客户端" + inetAddress + "连接成功!");
                // 调用多线程方法,每一个连上的客户端,服务器都有一个线程为之服务
                new MultiServerThread(s, inetAddress, listSocket).start();
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            try {
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }
}

上述代码实现服务器监听客户端连接,利用 accept 方法,每加入一个客户端,服务器都创建一个线程为之服务,同时将其加入一个List集合中,用来保存已加入聊天室的所有客户端。

处理收发信的线程

package Server;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Arrays;
import java.util.List;

public class MultiServerThread extends Thread {
    private Socket s;
    private InetAddress inetAddress;
    private List<Socket> listSockets;

    public MultiServerThread(Socket s, InetAddress inetAddress, List<Socket> listSockets) {
        this.s = s;
        this.inetAddress = inetAddress;
        this.listSockets = listSockets;
    }

    public void BroadCast(Socket s, byte[] by, int res)
    {
        // 将服务器接收到的消息发送给除了发送方以外的其他客户端
        int i = 0;
        for (Socket socket: listSockets)
        {
            if (s!=socket)  // 判断不是当前发送的客户端
            {
                System.out.println("发送给用户: " + listSockets.indexOf(socket));
                BufferedOutputStream ps = null;
                try {
                    ps = new BufferedOutputStream(socket.getOutputStream());
                    ps.write(by, 0, res);   // 写入输出流,将内容发送给客户端的输入流
                    ps.flush();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 服务器与客户端的交互线程
    @Override
    public void run() {
        BufferedInputStream ois = null;
        BufferedOutputStream oos = null;
        try {
            ois = new BufferedInputStream(s.getInputStream());

            oos = new BufferedOutputStream(s.getOutputStream());

            int i = 0;
            while (true) {
                //System.out.println("进入MultiChatServerThread");
                byte[] by = new byte[1024+2];
                //System.out.println("by.length: " + by.length);
                int res = 0;
                res = ois.read(by);
                // 对读取到的字节数组第一位位置进行修改,标识该数据流是由哪个用户发送来的
                by[0] = (byte)listSockets.indexOf(s);

                if (by[1] == 2){
                   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值