1.ChatRoom项目介绍

Create a chatroom with Java

项目配置:IntelliJ(jdk11),MySQL5

本文件会不断更新功能

GitHub账号:Guotianyu-2020

2022.2.13 Version1

此版本实现的功能有:本机上的两个客户端可以随意接收发送信息,并将两者发送的信息保存在MySQL数据库当中

此版本使用到的知识有:简单的java基础,多线程,JDBC连接,MySQL,Java服务器编程,极少的计算机网络知识

未来版本展望:制作UI界面,可以任意添加客户端数量

项目结构:

src目录下的三个目录分别归属客户端,MySQL数据库和服务器。

Server目录中TCPServer包含了主方法,ServerThread封装了服务器功能。在ServerThread中让服务器的两个线程同时监听两个客户端,将监听内容存入数据库相应表中,再将内容输出给另一个客户端以完成通信。

Client目录包含了两个客户端目录,以及客户端的读线程和写线程。先打开服务器端后,依次打开两个客户端。

MySQL目录下InsertMessage封装了插入方法,将服务器监听到的内容存入数据库表中

2022.3.6 Version2

此版本实现的功能有:在Version1的技术上添加了可视化界面,为每个客户设置单独的输入框和输出框,如图
GUI

此版本使用到的知识有:swing界面设计,多线程

未来版本展望:优化界面设计,设置群聊天,设置登录和注册功能

项目结构:

Client目录下两个客户端文件各自新增了界面线程,新增ClientGUI.java界面文件

2.源文件

2.1Version1源文件

客户端1、2:

package Client;

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

public class TCPClient1 {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("10.238.16.14", 8888);  // 服务端IP地址
        TCPClient1.runClient1(socket);
    }


    public static void runClient1(Socket socket) {
        ClientWriteThread cwt = new ClientWriteThread(socket);
        ClientListenThread clt = new ClientListenThread(socket);
        new Thread(() -> {
            while (!socket.isClosed()) {
                clt.listen();
            }
        }).start();
        new Thread(() -> {
            while (!socket.isClosed()) {
                cwt.write();
            }
        }).start();
    }
}
package Client;

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

public class TCPClient2 {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("10.238.16.14", 8888);
        TCPClient2.runClient2(socket);
    }


    public static void runClient2(Socket socket) {
        ClientWriteThread cwt = new ClientWriteThread(socket);
        ClientListenThread clt = new ClientListenThread(socket);
        new Thread(() -> {
            while (!socket.isClosed()) {
                clt.listen();
            }
        }).start();
        new Thread(() -> {
            while (!socket.isClosed()) {
                cwt.write();
            }
        }).start();
    }
}

客户端监听进程:

package Client;

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

public class ClientListenThread {
    private Socket socket;

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

    public void listen() {
        InputStream is;
        try {
            is = this.socket.getInputStream();
            byte[] bytes = new byte[1024];
            int len = is.read(bytes);
            System.out.println(new String(bytes, 0, len));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端写进程:

package Client;

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

public class ClientWriteThread {
    private Socket socket;

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

    public void write() {
        try {
            OutputStream os = this.socket.getOutputStream();
            Scanner sc = new Scanner(System.in);
            String s = sc.next();
            os.write(s.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端主方法:

package Server;

import java.io.IOException;

public class TCPServer {
    public static void main(String[] args) throws IOException {
            ServerThread st = new ServerThread(8888);
            st.runServer();
    }
}

服务端进程:

package Server;

import MySQL.InsertMessage;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerThread{
    private int port;
    private Socket socket1;
    private Socket socket2;


    public ServerThread(int port) {
        this.port = port;
    }


    public void runServer() throws IOException {
        ServerSocket server;
        server = new ServerSocket(this.port);
        this.socket1 = server.accept();
        this.socket2 = server.accept();
        System.out.println("两个客户端已经准备好");
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (true) {
                        InputStream is1 = socket1.getInputStream();
                        byte[] bytes = new byte[1024];
                        int len1 = is1.read(bytes);
                        String s1 = new String(bytes, 0, len1);
                        System.out.println("客户端1的消息是" + s1);
                        InsertMessage.insert(s1);
                        if (len1 != -1) {
                            OutputStream os = socket2.getOutputStream();
                            os.write(s1.getBytes());
                        }
                        System.out.println("已发出客户端1的消息");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (true) {
                        InputStream is2 = socket2.getInputStream();
                        byte[] bytes = new byte[1024];
                        int len2 = is2.read(bytes);
                        String s2 = new String(bytes, 0, len2);
                        System.out.println("客户端2的消息是" + s2);
                        InsertMessage.insert(s2);
                        if (len2 != -1) {
                            OutputStream os = socket1.getOutputStream();
                            os.write(s2.getBytes());
                        }
                        System.out.println("已发出客户端2的消息");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

服务端写入MySQL的方法:

package MySQL;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class InsertMessage {
    public static void insert(String massage) {
        Statement stmt = null;
        Connection conn = null;
        try {
            // 1.注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2.定义sql
            String sql = "insert into message values(null, '" + massage + "');";
            // 3.获取Connection对象
            conn = DriverManager.getConnection("jdbc:mysql:///chatroom", "root", "200818");
            // 4.获取执行sql的对象
            stmt = conn.createStatement();
            // 5.执行sql
            int count = stmt.executeUpdate(sql);
            // 6.处理结果
            System.out.println("已写入数据库");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            // 7.释放资源,注意要避免空指针异常
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
2.2Version2源文件

客户端1:

package Client;

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

public class TCPClient1 {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 8888);  // 服务端IP地址
        TCPClient1.runClient1(socket);
    }


    public static void runClient1(Socket socket) {
        ClientWriteThread cwt = new ClientWriteThread(socket);
        ClientListenThread clt = new ClientListenThread(socket);
        // 听线程
        new Thread(() -> {
            while (!socket.isClosed()) {
                clt.listen();
            }
        }).start();


        // 写线程
        new Thread(() -> {
            while (!socket.isClosed()) {
                if (ClientGUI.words != null) {
                    cwt.write();
                }
            }
        }).start();


        // GUI界面
        EventQueue.invokeLater(()->{
            ClientGUI.runGUI();
            ClientGUI.frame.setTitle("Client1");
        });
    }
}

写线程:

package Client;

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

public class ClientWriteThread {
    private Socket socket;

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

    public void write() {
        try {
            if (ClientGUI.words != null) {
                OutputStream os = this.socket.getOutputStream();
                os.write(ClientGUI.words.getBytes());
                ClientGUI.outputs.append("\n");
                ClientGUI.outputs.append(ClientGUI.words);
                ClientGUI.inputs.setText("");
                ClientGUI.words = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

读线程:

package Client;

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

public class ClientListenThread {
    private Socket socket;

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

    public void listen() {
        InputStream is;
        try {
            is = this.socket.getInputStream();
            byte[] bytes = new byte[1024];
            int len = is.read(bytes);
            String s = new String(bytes, 0, len);
            if (s != null) {
                ClientGUI.outputs.append("\n");
                ClientGUI.outputs.append(s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

GUI:

package Client;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ClientGUI {
    static JFrame frame = new JFrame();
    static String words;
    static JButton button = new JButton("发送");
    static JTextArea outputs = new JTextArea("消息:");
    static JTextArea inputs = new JTextArea();


    public static void runGUI(){
        // 流式布局
        frame.setLayout(new FlowLayout());
        // 获取Frame容器
        Container container = frame.getContentPane();
        // 设置窗体位置,大小
        frame.setBounds(400, 20, 400, 300);
        // 设置label大小
        outputs.setPreferredSize(new Dimension (360,100));
        // 设置文本区大小
        inputs.setPreferredSize(new Dimension (360,100));
        // 设置输入区自动换行
        inputs.setLineWrap(true);
        // 关闭窗口直接关掉进程
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 输出去设置不可编辑
        outputs.setEditable(false);


        // 添加组件
        container.add(outputs);
        container.add(inputs);
        container.add(button);
        frame.setVisible(true);
        // 事件触发不需要单独设置一个线程,放到GUI线程就行
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                ClientGUI.words = ClientGUI.inputs.getText();
            }
        });
    }
}
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐