java版本的聊天程序,数据通过mysql存储,不同用户相互聊天,查看历史记录,实时数据查看

 

 

 

 代码的实现

别忘了引入驱动

 

Client

package chat;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import com.mysql.cj.x.protobuf.MysqlxDatatypes.Array;

public class Client extends JFrame implements ActionListener {
	JComboBox cmb;
	JTextArea jta2, jta1, jt;
	Socket socket;
	String getname;
	String currentchatname;
	String getContent;
	byte[] b;
	String title;
	JLabel label1;
	String getAllUser[];
	String get = "";
	private static final int MESSAGE_SIZE = 1024;

	public Client() {
		createMidPanel();
		createSouthPanel();
		createNorthPanel();
		initFrame();
		try {
			socket = new Socket("127.0.0.1", 45678);
			if (socket.isConnected() == true) {
				System.out.println("连接成功");
				new Thread() {// 开启一个接受数据的线程
					@Override
					public void run() {
						super.run();
						b = new byte[MESSAGE_SIZE];

						try {
							InputStream in = socket.getInputStream();
							while (true) {
								Tools.resetArray(b);
								in.read(b);

								if (new String(b).contains("客户")) {
									int usernum = Tools.getNum(new String(b).trim());
									title = "用户" + usernum;
									jt.setText(title);
								} else {
									jta1.append(new String(b).trim() + "\n");

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

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

	}

	private void createNorthPanel() {
		JPanel north = new JPanel(new BorderLayout());
		label1 = new JLabel();
		jt = new JTextArea(1, 10);
		jt.setEditable(false); // 设置文本不可编辑
		jt.setFont(new Font("楷体", Font.BOLD, 20));
		jt.setBackground(new Color(241, 243, 244));
		jt.setForeground(new Color(143, 140, 138));
		label1.setForeground(new Color(143, 140, 138));
		north.add(jt, BorderLayout.WEST);
		north.add(label1, BorderLayout.CENTER);
		this.add(north, BorderLayout.NORTH);
	}

	private void createMidPanel() {

		JPanel midPanel = new JPanel();
		JPanel midPanel1 = new JPanel(new GridLayout(10, 1));
		jta1 = new JTextArea(7, 1);
		JScrollPane js1 = new JScrollPane(jta1);
		ResultSet result;
		try {
			result = new Tools().getData();

			while (result.next()) {
				get = get + result.getString(1) + " ";

			}

			String splict[] = get.split(" ");
			JButton ta[] = new JButton[splict.length];
			for (int i = 0; i < splict.length; i++) {
				ta[i] = new JButton(splict[i]);
				ta[i].setBackground(new Color(63, 174, 225));
				ta[i].setForeground(Color.white);
				if (splict[i].equals(title)) {
					ta[i].setEnabled(true);
				}
				ta[i].addActionListener(new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						// TODO Auto-generated method stub

						label1.setText("当前正与:" + e.getActionCommand() + "联系");
						currentchatname = e.getActionCommand();
						try {
							ResultSet set = new Tools().getData1(title, e.getActionCommand());

							jta1.setText("");
							while (set.next()) {
								if (set.getString(3).equals("发")) {
									jta1.append("我:" + set.getString(4) + "\n"+set.getString(5)+"\n");
								} else {
									jta1.append(e.getActionCommand() + ":" + set.getString(4) + "\n"+ set.getString(5)+"\n");
								}
							}
						} catch (SQLException e1) {
							e1.printStackTrace();
						}
					}

				});
				midPanel1.add(ta[i]);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		jta1.setLineWrap(true);// 自动换行
		jta1.setEditable(false); // 设置文本不可编辑
		jta1.setFont(new Font("楷体", Font.BOLD, 20));
		jta1.setBackground(new Color(152, 201, 238));
		jta1.setForeground(Color.white);
		jta2 = new JTextArea(5, 1);// 发送
		JScrollPane js2 = new JScrollPane(jta2);
		jta2.setLineWrap(true);// 自动换行
		// 在添加组建之前,更改布局
		midPanel.setLayout(new BorderLayout());
		midPanel.add(js1, BorderLayout.CENTER);
		midPanel.add(js2, BorderLayout.SOUTH);
		this.add(midPanel, BorderLayout.CENTER);
		this.add(midPanel1, BorderLayout.WEST);
	}

	private void createSouthPanel() {
		JPanel southPanel = new JPanel();// 创建一个面板对象
		JTextField southIP = new JTextField(10);
		southIP.setText("127.0.0.1");
		JButton jb1 = new JButton("发送");
		jb1.setBackground(new Color(40, 162, 223));
		jb1.setForeground(Color.white);
		JButton offline = new JButton("下线");
		offline.setBackground(new Color(40, 162, 223));
		offline.setForeground(Color.white);
		jb1.addActionListener(this);
		offline.addActionListener(this);
		southPanel.add(jb1);
		southPanel.add(offline);
		// 将面板添加到JFrame
		this.add(southPanel, BorderLayout.SOUTH);
	}

	private void initFrame() {
		ImageIcon titltIcon = new ImageIcon("C:\\Users\\DELL\\Desktop\\QQ.png");
		this.setIconImage(titltIcon.getImage());
		this.setTitle("聊天程序");
		this.pack(); // 刷新窗口组建
		this.setSize(600, 650);
		this.setBackground(new Color(152, 201, 238));
		this.setLocation(200, 50);
		this.setResizable(false);
		this.setVisible(true);// 设置窗体可见性
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		OutputStream out = null;
		if (e.getActionCommand().equals("发送")) {
			getname = currentchatname;
			getContent = jta2.getText();
			if (getContent.equals("")) {
				JOptionPane.showMessageDialog(null, "不能发送空白内容");
				return;
			}
			String send = Tools.getNum(getname) + " " + getContent;
			jta1.append("我" + ":" + getContent + "\n");

			jta2.setText("");
			try {
				new Tools().insertData(title, "发", getContent, currentchatname);
				new Tools().insertData(currentchatname, "接", getContent, title);
				out = socket.getOutputStream();
				out.write(send.getBytes());
				out.flush();

			} catch (IOException | SQLException e1) {
				e1.printStackTrace();
			}

		} else if (e.getActionCommand().equals("下线")) {
			try {
				out = socket.getOutputStream();
				out.write("end".getBytes());
				out.flush();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			System.exit(0);
			return;
		}
	}

	public static void main(String[] args) {
		// TODO自动生成的方法存根
		new Client();
	}

}

Server

package chat;

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

 
public class Server {

	List<ReceiveThread> receiveList = new ArrayList<>();// 存放已连接客户端类
	private final static int MESSAGE_SIZE = 1024;// 每次允许接受数据的最大长度
	int num = 0;// 客户端编号

	public static void main(String[] args) {
		new Server();
	}

	// 服务端处理逻辑
	Server() {
		ServerSocket serverSocket = null;
		try {
			serverSocket = new ServerSocket(45678);// 用来监听的套接字,指定端口号
			while (true) {
				Socket socket = serverSocket.accept();// 监听客户端连接,阻塞线程
				System.out.println("连接上客户端:" + num);
				// 在其他线程处理接收来自客户端的消息
				ReceiveThread receiveThread = new ReceiveThread(socket, num);
				receiveThread.start();
				receiveList.add(receiveThread);

				// 有客户端新上线,服务器就通知其他客户端
				String notice = "有新客户端上线,现在在线客户端有:客户端:";
				for (ReceiveThread thread : receiveList) {
					notice = notice + "" + thread.num;
				}
				for (ReceiveThread thread : receiveList) {
					// new SendThread(thread.socket, notice).start();
					new SendThread(thread.socket, "").start();
				}
				num++;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 接受消息的线程(同时也有记录对应客户端socket的作用)
	class ReceiveThread extends Thread {
		int num;
		Socket socket;// 客户端对应的套接字
		boolean continueReceive = true;// 标识是否还维持连接需要接收

		public ReceiveThread(Socket socket, int num) {
			this.socket = socket;
			this.num = num;
			try {
				// 给连接上的客户端发送,分配的客户端编号的通知
				socket.getOutputStream().write(("客户" + num).getBytes());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void run() {
			super.run();
			// 接收客户端发送的消息
			InputStream inputStream = null;
			try {
				inputStream = socket.getInputStream();
				byte[] b;
				while (continueReceive) {
					b = new byte[MESSAGE_SIZE];
					inputStream.read(b);
					b = Tools.splitByte(b);// 去掉数组无用部分
					// 发送end的客户端断开连接
					if (new String(b).equals("end")) {
						continueReceive = false;
						receiveList.remove(this);
						// 通知其他客户端
						String message = "客户" + num + "连接断开\n" + "现在在线的有,客户端:";
						for (ReceiveThread receiveThread : receiveList) {
							message = message + " " + receiveThread.num;
						}
					System.out.println(message);
						for (ReceiveThread receiveThread : receiveList) {
							new SendThread(receiveThread.socket, message).start();
						}
					} else {
						try {
							String[] data = new String(b).split(" ", 2);// 以第一个空格,将字符串分成两个部分
							int clientNum = Integer.parseInt(data[0]);// 转换为数字,即客户端编号数字						
							// 将消息发送给指定客户端
							for (ReceiveThread receiveThread : receiveList) {
								if (receiveThread.num == clientNum) {
									new SendThread(receiveThread.socket, "用户" + num + ":" + data[1].trim()).start();
									
								}
							}
						} catch (Exception e) {
							new SendThread(socket, "输入错误,请重新输入").start();
					
						}

					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {// 关闭资源
					if (inputStream != null) {
						inputStream.close();
					}
					if (socket != null) {
						socket.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	// 发送消息的线程
	class SendThread extends Thread {
		Socket socket;
		String str;

		public SendThread(Socket socket, String str) {
			this.socket = socket;
			this.str = str;
		}

		@Override
		public void run() {
			super.run();
			try {
				socket.getOutputStream().write(str.getBytes());
			//new 	jiemian1 ();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
	}



}

 Tools

package chat;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Tools {
	DBConn conn;
	Connection connection;

	public Tools() {
		conn = new DBConn();
		connection = conn.getConn();
	}
    public static String dataFormat() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date date = new Date();
			return format.format(date);
	}

	// 将byte数组置空
	public static byte[] resetArray(byte[] a) {
		byte[] b2 = new byte[a.length];
		for (int i = 0; i < a.length; i++) {
			a[i] = b2[i];
		}
		return a;
	}
	// 去除byte数组多余部分
	public static byte[] splitByte(byte b[]) {
		int i = 0;
		for (; i < b.length; i++) {
			if (b[i] == 0) {
				break;
			}
		}
		byte[] b2 = new byte[i];
		for (int j = 0; j < i; j++) {
			b2[j] = b[j];
		}
		return b2;
	}
    //将数据存入到数据库中
	public int insertData(String send, String detail, String content, String receive) throws SQLException {
		int result = 0;

		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date date = new Date();

		PreparedStatement st = connection
				.prepareStatement("insert into chat(send,data,data1,datetime,receive) values(?,?,?,?,?)");
		st.setString(1, send);
		st.setString(2, detail);
		st.setString(3, content);

		st.setString(4, format.format(date));
		st.setString(5, receive);
		result = st.executeUpdate();
		return result;
	}
   //获取所有的用户列表
	public ResultSet getData() throws SQLException {
		ResultSet result;

		connection = conn.getConn();
		PreparedStatement st1 = connection.prepareStatement("select client  from client");
		// PreparedStatement st1 = connection.prepareStatement("select DISTINCT send
		// from chat WHERE data='发'");
		result = st1.executeQuery();
		return result;
	}
   //查看用户其特定用户之间的信息交流
	public ResultSet getData1(String send, String receive) throws SQLException {
		ResultSet set;
		PreparedStatement st;
		st = connection.prepareStatement("select * from chat where send=? and receive=?");
		st.setString(1, send);
		st.setString(2, receive);
		set = st.executeQuery();
		return set;
	}
   // 获取后面的有效数字
	public static int getNum(String data) {
		int num = 0;
		String getresultnum = "";
		for (int i = 0; i < data.length(); i++) {
			Pattern pattern = Pattern.compile("[0-9]*");
			Matcher isNum = pattern.matcher(data.substring(i, i + 1));
			if (isNum.matches()) {
				getresultnum += data.substring(i, i + 1);
			} else
				getresultnum = "";

		}
		if (!getresultnum.equals("")) {
			num = Integer.parseInt(getresultnum);
		}
		return num;
	}
}

DBConn

package chat;

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

public class DBConn {
	private Connection dbConn;
	private String dbUrl = "jdbc:mysql://localhost:3306/chatgram";
	private String dbUser = "root";
	private String dbPwd = "123456";
	private String err;

	public DBConn() {
		err = "";
		dbConn = null;
	}
	public Connection getConn() {
		try {
				Class.forName("com.mysql.jdbc.Driver").newInstance();
			dbConn = DriverManager.getConnection(dbUrl, dbUser, dbPwd);
		} 
		catch (Exception ex) {
			dbConn = null;
			err = ex.toString();
			System.out.println(err);
		}
		return dbConn;

	}
	public String getErr() {
		return err;
	}

}

chatgram.sql

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 80017
Source Host           : localhost:3306
Source Database       : chatgram

Target Server Type    : MYSQL
Target Server Version : 80017
File Encoding         : 65001

Date: 2022-09-04 21:22:02
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for chat
-- ----------------------------
DROP TABLE IF EXISTS `chat`;
CREATE TABLE `chat` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `send` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
  `data` varchar(10) DEFAULT NULL,
  `data1` varchar(100) DEFAULT NULL,
  `datetime` varchar(100) DEFAULT NULL,
  `receive` varchar(12) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=317 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- ----------------------------
-- Records of chat
-- ----------------------------
INSERT INTO `chat` VALUES ('239', '用户0', '发', 'hello', '2022-07-02 16:44:29', '用户1');
INSERT INTO `chat` VALUES ('240', '用户1', '接', 'hello', '2022-07-02 16:44:29', '用户0');
INSERT INTO `chat` VALUES ('241', '用户0', '发', '你好', '2022-07-02 16:54:05', '用户1');
INSERT INTO `chat` VALUES ('242', '用户1', '接', '你好', '2022-07-02 16:54:05', '用户0');
INSERT INTO `chat` VALUES ('243', '用户1', '发', '我是apple', '2022-07-02 16:55:42', '用户0');
INSERT INTO `chat` VALUES ('244', '用户0', '接', '我是apple', '2022-07-02 16:55:42', '用户1');
INSERT INTO `chat` VALUES ('245', '用户0', '发', '我是boy', '2022-07-02 16:55:52', '用户1');
INSERT INTO `chat` VALUES ('246', '用户1', '接', '我是boy', '2022-07-02 16:55:52', '用户0');
INSERT INTO `chat` VALUES ('307', '用户1', '发', '2022/7/3', '2022-07-03 10:03:20', '用户0');
INSERT INTO `chat` VALUES ('308', '用户0', '接', '2022/7/3', '2022-07-03 10:03:20', '用户1');
INSERT INTO `chat` VALUES ('309', '用户1', '发', '你下线了', '2022-07-03 10:10:11', '用户0');
INSERT INTO `chat` VALUES ('310', '用户0', '接', '你下线了', '2022-07-03 10:10:11', '用户1');
INSERT INTO `chat` VALUES ('311', '用户1', '发', '你好我是用户1', '2022-07-04 13:04:25', '用户0');
INSERT INTO `chat` VALUES ('312', '用户0', '接', '你好我是用户1', '2022-07-04 13:04:25', '用户1');
INSERT INTO `chat` VALUES ('313', '用户0', '发', '在线', '2022-07-04 13:04:47', '用户2');
INSERT INTO `chat` VALUES ('314', '用户2', '接', '在线', '2022-07-04 13:04:47', '用户0');
INSERT INTO `chat` VALUES ('315', '用户0', '发', '2022、9、4', '2022-09-04 21:11:58', '用户1');
INSERT INTO `chat` VALUES ('316', '用户1', '接', '2022、9、4', '2022-09-04 21:11:58', '用户0');

-- ----------------------------
-- Table structure for client
-- ----------------------------
DROP TABLE IF EXISTS `client`;
CREATE TABLE `client` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `client` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- ----------------------------
-- Records of client
-- ----------------------------
INSERT INTO `client` VALUES ('1', '用户0');
INSERT INTO `client` VALUES ('2', '用户1');
INSERT INTO `client` VALUES ('3', '用户2');
INSERT INTO `client` VALUES ('4', '用户3');
INSERT INTO `client` VALUES ('5', '用户4');
INSERT INTO `client` VALUES ('6', '用户5');

缺点是每开一个线程才代表一个用户上线

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值