Java多人聊天室(网络编程)

使用基于 tcp 协议的编程模型实现多人同时在线聊天,要求每个客户端将发 送的聊天内容发送到服务器,服务器接收到后转发给当前所有在线的客户端。

这题说难并不难,主要看自己掌握Socket的熟练程度。反正我是卡了很久。各种奇怪的报错。

解题思路:
每台客户端两条线程,服务器端一条线程加上对应客户端的一条线程(每启动一个客户端,服务器端生成一条线程)

难点总结:
流的释放。

服务器端

package test4.Server;

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

/**
 * @author: gk
 * @date: 2021年01月19日 11:22
 */
    public class Server {
    
    
    static List<Socket> sockets = new ArrayList<>();
    public static void main(String[] args) {
    
    
        ServerSocket serverSocket = null;
        Socket socket = null;
        try {
    
    
            //1.创建ServerSocket类型的对象并提供端口号
            serverSocket = new ServerSocket(8888);
            System.out.println("服务端已启动...");
            //2.等待客户端的连接请求,调用accept方法
            while (true){
    
    
                socket = serverSocket.accept();
                sockets.add(socket);
                System.out.println("客户端" + socket.getInetAddress() + "连接成功!");
                new ServerThread(sockets,socket).start();
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //4.关闭Socket并释放有关的资源
            if(null != serverSocket){
    
    
                try {
    
    
                    serverSocket.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
}

连接线程

package test4.Server;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: gk
 * @date: 2021年01月18日 15:05
 */
public class ServerThread extends Thread{
    
    
    private Socket socket;
    private List<Socket> sockets;
    public ServerThread(List<Socket> sockets,Socket socket) {
    
    
        this.sockets = sockets;
        this.socket = socket;
    }

    @Override
    public void run() {
    
    
        BufferedReader br = null;
        /*PrintStream ps = null;*///字符流全部改回字节流(统一规范)
        PrintWriter pw = null;
        try {
    
    
            System.out.println(Thread.currentThread().getId()+":"+Thread.currentThread().getName());
            //3.使用输入输出流进行通信
            br =new BufferedReader(new InputStreamReader(socket.getInputStream()));
            bye:while (true){
    
    
                //实现对客户端发来字符串内容的接收并打印
                String str = null;
                try {
    
    
                    str = br.readLine();
                } catch (IOException e) {
    
    
                    //修复BUG时用来获取错误信息(获取哪条线程出错/已解决,可删除)
                    System.out.println("错误------"+Thread.currentThread().getId()+":"+Thread.currentThread().getName());
                    e.printStackTrace();
                }
                //拿客户端发送来的数据进行分解
                String[] strings = str.split(":");
                System.out.println("客户端[" +Thread.currentThread().getName()+":"+ strings[0]  + "]发送来的内容是:" + strings[1]);
                //实现服务器向所有客户端(包括自己)发送传递进来的信息
                for (Socket socket:sockets) {
    
    
                    boolean flag = false;
                    flag = socket.getKeepAlive();//判断socket的状态
                    if (!flag){
    
    
                            pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
                            pw.println(str);
                            pw.flush();
//                            ps = new PrintStream(socket.getOutputStream());
//                            ps.println(str);
//                            ps.flush();
                    }
                }
                //发送结束,服务端自己做出提示(记入日志)
                System.out.println("已将发来的数据"+str+"转发给其他客户端!");
                //当客户端发来的内容为"bye"时,则聊天结束
                if ("bye".equalsIgnoreCase(strings[1])){
    
    
                    System.out.println("客户端" + socket.getInetAddress() + "下线~");
                    System.out.println("结束------"+Thread.currentThread().getId()+":"+Thread.currentThread().getName());
                    sockets.remove(socket);
                    break bye;
                }
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    //关闭所有流
            /**不知道为啥ps/pw关闭就出错,所以不关了*/
            if(null != socket){
    
    
                try {
    
    
                    socket.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
            if(null != br){
    
    
                try {
    
    
                    br.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
}

客户端

package test4.Server;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * @Description: TODO
 * @author: gk
 * @date: 2021年01月18日 14:20
 */
public class Client {
    
    
    private String user;//客户端标识
    Socket socket = null;
    //PrintStream ps = null;
    Scanner sc = null;
    BufferedReader br = null;


    PrintWriter pw=null;

    public Client(String user, Socket socket) {
    
    
        try {
    
    
            this.user = user;
            //ps = new PrintStream(socket.getOutputStream());
            pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            sc = new Scanner(System.in);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }

    /**
     * 发送信息
     * @return
     */
    public Thread send(){
    
    
        return new Thread(){
    
    
            @Override
            public void run() {
    
    
                //2.使用输入输出流进行通信
                bye:while (true) {
    
    
                    System.out.println("请输入要发送的内容");
                    String str = sc.next();
                    //实现客户端向服务器发送字符申内容
                    pw.println(user + ":" + str);
                    pw.flush();
                    System.out.println("客户端发送数据内容成功!");
                    //当发送的数据内容为"bye"时,则聊天结束
                    if ("bye".equalsIgnoreCase(str)) {
    
    
                        System.out.println("聊天结束!");
                        break bye;
                    }
                }
            }
        };
    }
    /***
     * 接收信息线程
     * @return
     */
    public Thread receive(){
    
    
        return new Thread(){
    
    
            @Override
            public void run() {
    
    
                bye:while (true){
    
    
                    String str = null;
                    try {
    
    //获取服务端发送过来的数据
                        str = br.readLine();
                    } catch (IOException e) {
    
    
                        e.printStackTrace();
                    }
                    //服务端发送过来的数据进行分解
                    String[] strings = str.split(":");
                    if (user.equalsIgnoreCase(strings[0])){
    
    
                        System.out.println("[自己]:"+strings[1]);
                        //读取到bye,退出
                        if ("bye".equalsIgnoreCase(strings[1])){
    
    
                            System.out.println("退出聊天室!");
                            break bye;
                        }
                    }else {
    
    
                        //其他人的信息
                        System.out.println("[" + strings[0]+"]:"+strings[1]);
                    }
                }
            }
        };
    }

    /**
     * 3.关闭Socket并释放有关的资渊
     */
    public void close(){
    
    
        if(null != br){
    
    
            try {
    
    
                br.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
//        if(null != ps){
    
    
//            ps.close();
//        }
        if(null != pw){
    
    
           pw.close();
       }
        if(null != sc){
    
    
            sc.close();
        }
        if(null != socket){
    
    
            try {
    
    
                socket.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

实现类

package test4.Server;

import java.io.IOException;
import java.net.Socket;

/**
 * @author: gk
 * @date: 2021年01月19日 12:52
 */
public class ClientTest1 {
    
    
    public static void main(String[] args) {
    
    
        Socket socket = null;
        try {
    
    
            socket = new Socket("127.0.0.1",8888);
            System.out.println("连接服务器成功");
            Client c1 = new Client("石头",socket);//创建一个客户端实例
            Thread t1 = c1.send();//获取发送消息线程
            Thread t2 = c1.receive();//获取接收消息线程
            t2.start();
            t1.start();
            //t1.join();
            //t2.join();
            //c1.close();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Guai_Ka/article/details/113102546