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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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); 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(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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(); } }
|
客户端监听进程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 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(); } } }
|
客户端写进程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| 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(); } } }
|
服务端主方法:
1 2 3 4 5 6 7 8 9 10
| package Server;
import java.io.IOException;
public class TCPServer { public static void main(String[] args) throws IOException { ServerThread st = new ServerThread(8888); st.runServer(); } }
|
服务端进程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| 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的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| 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 { Class.forName("com.mysql.cj.jdbc.Driver"); String sql = "insert into message values(null, '" + massage + "');"; conn = DriverManager.getConnection("jdbc:mysql:///chatroom", "root", "200818"); stmt = conn.createStatement(); int count = stmt.executeUpdate(sql); System.out.println("已写入数据库"); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } finally { 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| 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); 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();
EventQueue.invokeLater(()->{ ClientGUI.runGUI(); ClientGUI.frame.setTitle("Client1"); }); } }
|
写线程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| 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(); } } }
|
读线程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 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()); Container container = frame.getContentPane(); frame.setBounds(400, 20, 400, 300); 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); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { ClientGUI.words = ClientGUI.inputs.getText(); } }); } }
|