赞
踩
工程构成如下图:
1、ClientGUI包里面
(1)LogOn.java代码如下:
- package ClientGUI;
-
- import java.awt.BorderLayout;
- import java.awt.FlowLayout;
- import java.awt.GridLayout;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
-
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JLabel;
- import javax.swing.JOptionPane;
- import javax.swing.JPanel;
- import javax.swing.JPasswordField;
- import javax.swing.JTextField;
- import javax.swing.SwingUtilities;
- import javax.swing.UIManager;
-
- import ClientSide.Client;
- import ClientSide.Client.ClientThread;
- import ServerSide.Server;
-
- //登录窗口
- public class LogOn extends JFrame implements ActionListener {
-
- private Register register;
-
- private ClientThread clientThread;
-
- private Server server=Server.GetServer();
-
- private JLabel jlUserName;
-
- private JLabel jlPassword;
-
- private JTextField jtUserName;
-
- private JPasswordField jpPassword;
-
- private JButton jbLogOn;
-
- private JButton jbRegister;
-
- private JPanel jpDown;
-
- private JPanel jpCenter;
-
- public LogOn() {
- Init();
- }
-
- private void Init() {
- jlUserName = new JLabel("用户名");
- jlPassword = new JLabel("密 码");
- jtUserName = new JTextField(15);
- jpPassword = new JPasswordField(15);
- jbLogOn = new JButton("登录");
- jbRegister = new JButton("注册");
-
- jbLogOn.addActionListener(this);
- jbRegister.addActionListener(this);
-
- jpCenter = new JPanel();
- jpCenter.setLayout(new GridLayout(2, 2));
- jpCenter.add(jlUserName);
- jpCenter.add(jtUserName);
- jpCenter.add(jlPassword);
- jpCenter.add(jpPassword);
-
- jpDown = new JPanel();
- jpDown.setLayout(new FlowLayout());
- jpDown.add(jbLogOn);
- jpDown.add(jbRegister);
-
- this.setLayout(new BorderLayout());
- this.add("Center", jpCenter);
- this.add("South", jpDown);
-
- this.setTitle("用户登录界面");
- this.setSize(350, 150);
- this.setLocationRelativeTo(null);
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- this.setVisible(true);
-
- // 更改窗体样式
- try {
- String style = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
- UIManager.setLookAndFeel(style);
- SwingUtilities.updateComponentTreeUI(this);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
-
- @Override
- public void actionPerformed(ActionEvent e) {
- Object source = e.getSource();
- if (source == jbLogOn) {
- //判断是否为空
- if(jtUserName.getText()==null || jtUserName.getText().equals("")
- || String.valueOf(jpPassword.getPassword())==null ||
- String.valueOf(jpPassword.getPassword()).equals(""))
- {
- JOptionPane.showMessageDialog(null, "请输入账号或者密码");
- }else
- {
- if(server.LogOn(jtUserName.getText(), String.valueOf(jpPassword.getPassword())))
- {
- MainUI mainUI=new MainUI(jtUserName.getText());
- Client client=Client.GetClient();
- client.SetMainUI(mainUI);
- client.SetUserName(mainUI.GetUserName());
- clientThread=client.new ClientThread();
- client.SetClientThread(clientThread);
- clientThread.start();
- this.setVisible(false);
- }else
- {
- JOptionPane.showMessageDialog(null, "账号或者密码错误");
- }
- }
- } else if (source == jbRegister) {
- register=new Register(this);
- this.setVisible(false);
- }
-
- }
-
- public static void main(String[] args) {
- new LogOn();
- }
-
- }
(2)MainUI代码如下:
- package ClientGUI;
-
- import java.awt.Color;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
-
- import javax.swing.ButtonGroup;
- import javax.swing.DefaultListModel;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JLabel;
- import javax.swing.JList;
- import javax.swing.JRadioButton;
- import javax.swing.JScrollPane;
- import javax.swing.JTextArea;
- import javax.swing.JTextField;
- import javax.swing.ListSelectionModel;
- import javax.swing.SwingUtilities;
- import javax.swing.UIManager;
-
- import ClientSide.Client;
-
- public class MainUI{
-
- // private static MainUI mainUIInstance=null;
- //
- // public static synchronized MainUI GetMainUI()
- // {
- // if(mainUIInstance==null)
- // {
- // mainUIInstance=new MainUI();
- // }
- // return mainUIInstance;
- // }
- //
-
- private JFrame frmtcp;
- private JTextField textServerIP;// IP
- private JTextField textServerPort;// 端口
- private JTextArea textAreaRecord;// 消息文本记录框
- private JButton btnSend;// 发送按钮
- private JButton btnQuit;// 退出按钮
- private JLabel jlUsername;// 用户名
- private JList<String> listUsers;// 用户列表 Jlist控件显示客户端的用户列表。数据保存在DefaultListmodel数据模型对象中。
- private final ButtonGroup buttonGroup = new ButtonGroup();
- private JRadioButton rdbtnBrocast;// 群聊
- private JRadioButton rdbtnPrivateChat;// 私聊
- private JTextArea textAreaMsg;// 消息框
- private DefaultListModel<String> modelUsers;// 数据模型,用于更新数据
-
- public JTextField GetTextServerIP()
- {
- return textServerIP;
- }
- public JTextField GetTextServerPort()
- {
- return textServerPort;
- }
- public void SetUserName(String userName)
- {
- jlUsername.setText(userName);
- }
- public String GetUserName()
- {
- return jlUsername.getText();
- }
- public JTextArea GetTextAreaMsg()
- {
- return textAreaMsg;
- }
- public JButton GetBtnQuit()
- {
- return btnQuit;
- }
- public JButton GetBtnSend()
- {
- return btnSend;
- }
- public JList<String> GetListUsers()
- {
- return listUsers;
- }
- public DefaultListModel<String> GetModelUsers()
- {
- return modelUsers;
- }
- public JRadioButton GetRdbtnBrocast()
- {
- return rdbtnBrocast;
- }
- public JRadioButton GetRdbtnPrivateChat()
- {
- return rdbtnPrivateChat;
- }
-
- public JTextArea GetTextAreaRecord()
- {
- return textAreaRecord;
- }
-
- public JFrame GetJfrmtcp()
- {
- return frmtcp;
- }
- public MainUI(String userName)
- {
- Init(userName);
- modelUsers = new DefaultListModel();
- modelUsers = new DefaultListModel<String>();
- listUsers.setModel(modelUsers);
-
- }
- private void Init(String userName)
- {
- frmtcp = new JFrame();
- frmtcp.setResizable(false);
- frmtcp.setTitle("聊天主界面");
- frmtcp.setBounds(100, 100, 715, 476);
- frmtcp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frmtcp.getContentPane().setLayout(null);
- frmtcp.setVisible(true);
-
-
- // IP
- JLabel lblNewLabel = new JLabel("服务器IP地址:");
- lblNewLabel.setBounds(14, 24, 121, 18);
- frmtcp.getContentPane().add(lblNewLabel);
- textServerIP = new JTextField();
- textServerIP.setText("127.0.0.1");
- textServerIP.setBounds(121, 21, 121, 24);
- frmtcp.getContentPane().add(textServerIP);
- textServerIP.setColumns(10);
-
- // 端口
- JLabel lblNewLabel_1 = new JLabel("端口号:");
- lblNewLabel_1.setBounds(256, 24, 58, 18);
- frmtcp.getContentPane().add(lblNewLabel_1);
- textServerPort = new JTextField();
- textServerPort.setText("6666");
- textServerPort.setBounds(313, 21, 48, 24);
- frmtcp.getContentPane().add(textServerPort);
- textServerPort.setColumns(10);
-
- // 用户名
- JLabel label_1 = new JLabel("用户名:");
- label_1.setBounds(375, 24, 58, 18);
- frmtcp.getContentPane().add(label_1);
- jlUsername = new JLabel(userName);
- jlUsername.setBounds(433, 21, 95, 24);
- frmtcp.getContentPane().add(jlUsername);
-
- //退出按钮
- btnQuit = new JButton("退出");
- btnQuit.setBounds(596, 20, 95, 27);
- frmtcp.getContentPane().add(btnQuit);
- btnQuit.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent arg0) {
-
-
-
- }
- });
-
-
-
- // 发送按钮
- btnSend = new JButton("发送");
- btnSend.setEnabled(false);
- btnSend.setBounds(444, 409, 88, 27);
- frmtcp.getContentPane().add(btnSend);
- // 连接按钮事件处理程序
- btnSend.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent arg0) {
-
- }
- });
-
- // 聊天记录框
- JLabel label = new JLabel("聊天区");
- label.setBounds(14, 55, 72, 18);
- frmtcp.getContentPane().add(label);
- JScrollPane scrollPane = new JScrollPane();
- scrollPane.setBounds(14, 72, 518, 228);
- frmtcp.getContentPane().add(scrollPane);
- textAreaRecord = new JTextArea();
- textAreaRecord.setBackground(Color.pink);
- textAreaRecord.setEditable(false);
- scrollPane.setViewportView(textAreaRecord);
-
-
- // 消息输入框
- JScrollPane scrollPane_1 = new JScrollPane();
- scrollPane_1.setBounds(14, 332, 518, 73);
- frmtcp.getContentPane().add(scrollPane_1);
- textAreaMsg = new JTextArea();
- scrollPane_1.setViewportView(textAreaMsg);
-
- JLabel label_2 = new JLabel("在线用户");
- label_2.setBounds(543, 55, 72, 18);
- frmtcp.getContentPane().add(label_2);
-
- // 用户列表框
- JScrollPane scrollPane_2 = new JScrollPane();
- scrollPane_2.setBounds(546, 72, 149, 334);
- frmtcp.getContentPane().add(scrollPane_2);
- listUsers = new JList<String>();
- listUsers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- scrollPane_2.setViewportView(listUsers);
-
- rdbtnBrocast = new JRadioButton("群聊");
- buttonGroup.add(rdbtnBrocast);
- rdbtnBrocast.setBounds(66, 306, 104, 22);
- frmtcp.getContentPane().add(rdbtnBrocast);
- rdbtnBrocast.setSelected(true);
- rdbtnPrivateChat = new JRadioButton("私聊");
- buttonGroup.add(rdbtnPrivateChat);
- //rdbtnPrivateChat.setSelected(true);
- rdbtnPrivateChat.setBounds(192, 306, 72, 22);
- frmtcp.getContentPane().add(rdbtnPrivateChat);
-
-
- // 更换样式
- try {
- String style = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
- UIManager.setLookAndFeel(style);
- // 更新窗体样式
- SwingUtilities.updateComponentTreeUI(this.frmtcp);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- }
(3)Register代码如下:
- package ClientGUI;
-
- import java.awt.BorderLayout;
- import java.awt.FlowLayout;
- import java.awt.GridLayout;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
-
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JLabel;
- import javax.swing.JOptionPane;
- import javax.swing.JPanel;
- import javax.swing.JPasswordField;
- import javax.swing.JTextField;
- import javax.swing.SwingUtilities;
- import javax.swing.UIManager;
-
- import ClientSide.Client;
- import ServerSide.Server;
-
- //注册窗口
- public class Register extends JFrame implements ActionListener {
-
-
- private LogOn logOn;
-
- private JLabel jlUserName;
-
- private JLabel jlPassword;
-
- private JTextField jtUserName;
-
- public JTextField GetJtUserName()
- {
- return jtUserName;
- }
-
- private JPasswordField jpPassword;
-
- private JButton jbreturn;
-
- private JButton jbRegister;
-
- private JPanel jpDown;
-
- private JPanel jpCenter;
-
- private Server server = Server.GetServer();
-
- public Register(LogOn logOn) {
- Init(logOn);
- }
-
- private void Init(LogOn logOn) {
- this.logOn=logOn;
- jlUserName = new JLabel("用户名");
- jlPassword = new JLabel("密 码");
- jtUserName = new JTextField(15);
- jpPassword = new JPasswordField(15);
- jbreturn = new JButton("返回");
- jbRegister = new JButton("注册");
-
- jbreturn.addActionListener(this);
- jbRegister.addActionListener(this);
-
- jpCenter = new JPanel();
- jpCenter.setLayout(new GridLayout(2, 2));
- jpCenter.add(jlUserName);
- jpCenter.add(jtUserName);
- jpCenter.add(jlPassword);
- jpCenter.add(jpPassword);
-
- jpDown = new JPanel();
- jpDown.setLayout(new FlowLayout());
- jpDown.add(jbRegister);
- jpDown.add(jbreturn);
-
- this.setLayout(new BorderLayout());
- this.add("Center", jpCenter);
- this.add("South", jpDown);
-
- this.setTitle("用户注册界面");
- this.setSize(350, 150);
- this.setLocationRelativeTo(null);
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- this.setVisible(true);
-
- // 更改窗体样式
- try {
- String style = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
- UIManager.setLookAndFeel(style);
- SwingUtilities.updateComponentTreeUI(this);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void actionPerformed(ActionEvent e) {
- Object source = e.getSource();
- if (source == jbreturn) {
- logOn.setVisible(true);
- this.setVisible(false);
-
- } else if (source == jbRegister) {
- // 判断是否为空
- if (jtUserName.getText() == null || jtUserName.getText().equals("")
- || String.valueOf(jpPassword.getPassword()) == null
- || String.valueOf(jpPassword.getPassword()).equals("")) {
- JOptionPane.showMessageDialog(null, "请输入账号和密码");
- } else {
- // 数据传给服务器进行注册
- if (server.Register(jtUserName.getText(), String.valueOf(jpPassword.getPassword()))) {
- JOptionPane.showMessageDialog(null, "注册成功");
- }else {
- JOptionPane.showMessageDialog(null, "注册失败,改用户名已注册");
- }
- }
- }
-
- }
-
- }
2、ClientSide包里面
(1)Client代码如下:
- package ClientSide;
-
- import java.awt.Component;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.IOException;
- import java.net.Socket;
-
- import javax.swing.JButton;
- import javax.swing.JList;
- import javax.swing.JOptionPane;
-
- import ClientGUI.MainUI;
- import ClientGUI.Register;
- import Utils.Utils;
-
- public class Client{
-
- private static Client clientInstance=null;
- public static synchronized Client GetClient()
- {
- if(clientInstance==null)
- {
- clientInstance=new Client();
- }
- return clientInstance;
- }
-
- private MainUI mainUI;
- public void SetMainUI(MainUI mainUI)
- {
- this.mainUI=mainUI;
- }
-
- private ClientThread clientThread;
- public void SetClientThread(ClientThread clientThread)
- {
- if(clientThread!=null)
- {
- this.clientThread=clientThread;
- }
- }
-
-
- private String username;
-
- public void SetUserName(String userName)
- {
- this.username=userName;
- }
-
-
-
-
- // 内部类.客户端线程,负责与服务器交互
- public class ClientThread extends Thread{
- private final Component frmtcp = null;
- // 通信套接字
- private Socket socket;
- // 基本数据输入流
- private DataInputStream dis;
- // 基本数据输出流
- private DataOutputStream dos;
- // 是否登录
- private boolean isLogged;
-
- // 连接服务器
- public void ConnectServer() {
- // 获取服务器IP地址和端口
- String serverIp = mainUI.GetTextServerIP().getText();
- int serverPort = Integer.parseInt(mainUI.GetTextServerPort().getText());
- try {
- // 连接服务器,获取套接字IO流
- socket = new Socket(serverIp, serverPort);
- dis = new DataInputStream(socket.getInputStream());
- dos = new DataOutputStream(socket.getOutputStream());
- // 获取用户名,构建、发送登录报文
- //String username = mainUI.GetUserName();
-
- String msgConnect = "CONNECT#" + username;
- dos.writeUTF(msgConnect);
- dos.flush();
-
- // 读取服务器返回的信息,判断是否登录成功
- String response = dis.readUTF();
-
- // 登录失败
- if (response.equals("FAIL")) {
- addMsg("username+连接服务器失败");
- dis.close();
- dos.close();
- socket.close();
- return;
- } else {
- addMsg(username+"上线了!");
- isLogged = true;
- mainUI.GetBtnQuit().setText("退出");
- mainUI.GetBtnSend().setEnabled(true);
- String[] self = { username };
- UpdateJList(mainUI.GetListUsers(), self, "ADD");
- }
-
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- // 退出聊天室功能实现
- public void DisConnectServer() {
- try {
- Utils.sendMsg(socket, "DISCONNECT#" + username);
- mainUI.GetModelUsers().clear();
- mainUI.GetListUsers().setModel(mainUI.GetModelUsers());
- addMsg(username+"下线了");
- isLogged=false;
- mainUI.GetBtnQuit().setEnabled(false);
- mainUI.GetBtnSend().setEnabled(false);
- String[] self = { username };
- UpdateJList(mainUI.GetListUsers(), self, "DEL");
- dis.close();
- dos.close();
- socket.close();
- clientThread.interrupt();
- } catch (IOException e) {
-
- e.printStackTrace();
- }
- }
-
- // 更新用户列表
- public void UpdateJList(JList jList, String[] items, String op) {
- switch (op) {
- case "ADD": // 添加新数据
- for (int i = 0; i < items.length; ++i) {
- mainUI.GetModelUsers().addElement(items[i]);
- break;
- }
- case "DEL":// 删除数据
- for (int i = 0; i < items.length; ++i) {
- mainUI.GetModelUsers().removeElement(items[i]);
- break;
- }
- default:
- break;
- }
- jList.setModel(mainUI.GetModelUsers());// 更新数据
-
- }
-
- // 发送消息
- public void SendChatMsg() {
-
- String msgChat = null;
- String dstUser = "所有人";
- if (mainUI.GetRdbtnBrocast().isSelected()) {
- msgChat = "TALKTO_ALL#" + mainUI.GetTextAreaMsg().getText();
- }
- if (mainUI.GetRdbtnPrivateChat().isSelected()) {
- dstUser = (String) mainUI.GetListUsers().getSelectedValue();
- if (dstUser == null) {
- JOptionPane.showMessageDialog(this.frmtcp, "请选择需要私聊的用户!");
- return;
- }
- msgChat = "TALKTO#" + dstUser + "#" + mainUI.GetTextAreaMsg().getText();
- }
- // 发送聊天报文到服务器
- Utils.sendMsg(socket, msgChat);
- // 添加到消息记录框
- addMsg(" 我对" + dstUser + "说:" + mainUI.GetTextAreaMsg().getText());
- // if (null != msgChat) {
- // try {
- // dos.writeUTF(msgChat);
- // dos.flush();
- // } catch (IOException e) {
- // e.printStackTrace();
- // }
- // }
-
- }
-
-
-
- // 线程主体
- @Override
- public void run() {
- ConnectServer();
- //发送消息按钮
- mainUI.GetBtnSend().addActionListener(new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- SendChatMsg();
-
- }
- });
- //退出按钮
- mainUI.GetBtnQuit().addActionListener(new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- DisConnectServer();
-
- }
- });
-
- //消息处理
- while (isLogged) {
- try {
-
-
- String msg = dis.readUTF();
- String[] parts = msg.split("#");
-
- switch (parts[0]) {
- // 处理服务器发来的用户列表报文
- case "USERLIST":
- String[] self = { username };
- UpdateJList(mainUI.GetListUsers(), self, "ADD");
- for (int i = 1; i < parts.length; i++) {
- mainUI.GetModelUsers().addElement(parts[i]);
- }
- break;
- // 处理服务器发来的新用户连接表报文
- case "CONNECT":
- mainUI.GetModelUsers().addElement(parts[1]);
- addMsg(" " + parts[1] + "上线了");
- break;
- case "DISCONNECT":
- mainUI.GetModelUsers().removeElement(parts[1]);
- addMsg(" " + parts[1] + "下线了");
- break;
- case "TALKTO_ALL":
- addMsg(parts[1] + " 跟所有人说:" + parts[2]);
- break;
- case "TALKTO":
- addMsg(parts[1] + " 跟我说:" + parts[2]);
- break;
- default:
- break;
- }
- } catch (IOException e) {
- isLogged = false;
- e.printStackTrace();
- }
-
- }
-
- }
-
-
- // 添加消息到文本框textAreaRecord
- public void addMsg(String msg) {
- // 在文本区中添加一条消息,并加上换行
- mainUI.GetTextAreaRecord().append(msg + "\n");
- // 自动滚动到文本区的最后一行
- mainUI.GetTextAreaRecord().setCaretPosition(mainUI.GetTextAreaRecord().getText().length());
- }
-
-
- }
-
-
- }
3、ConnectMysql包里面
(1)Connect代码如下:
- package ConnectMysql;
-
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
-
- public class Connect {
-
- private Connection con;
-
- public Connection GetConnection() {
- try {
- Class.forName("com.mysql.cj.jdbc.Driver");
- System.out.println("数据库驱动加载成功");
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- try {
- con = DriverManager.getConnection("jdbc:mysql://localhost:3306/student?useSSL=false&serverTimezone=UTC",
- "root", "249913");
- System.out.println("数据库连接成功");
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return con;
- }
-
- //关闭数据库
- public void CloseConn(ResultSet rs, PreparedStatement pstm, Connection conn) throws Exception {
- if (rs != null) {
- rs.close();
- }
- if (pstm != null) {
- pstm.close();
- }
- if (conn != null) {
- conn.close();
- }
- }
-
- }
(2)OperatorMysql代码如下
- package ConnectMysql;
-
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
-
-
- public class OperatorMysql {
-
- Connect connect = new Connect();
-
- private Connection con;
-
- // 增加数据(增加数据前先查询用户名是否已存在)
- public void Insert(String userName, String userPassword) {
- con = connect.GetConnection();
- PreparedStatement pstm = null;
- String sql_insert = "insert into user(userName,userPassword) values(?,?)";
- try {
- pstm = con.prepareStatement(sql_insert);
- pstm.setString(1, userName);
- pstm.setString(2, userPassword);
- pstm.executeUpdate();
- connect.CloseConn(null, pstm, con);
-
- } catch (SQLException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- // 查找数据(用户名重复返回false)
- public Boolean Search(String userName) {
- con = connect.GetConnection();
- PreparedStatement pstm = null;
- ResultSet rs = null;
- String sql_Search = "select *from user where userName=?";
- try {
- pstm = con.prepareStatement(sql_Search);
- pstm.setString(1, userName);
- rs = pstm.executeQuery();
- if(rs.next())
- {
- return false;
- }
-
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return true;
- }
-
- }
4、ServerGUI包里面
(1)ServerUI代码如下:
- package ServerGUI;
-
- import java.awt.Color;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.io.IOException;
-
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JLabel;
- import javax.swing.JScrollPane;
- import javax.swing.JTable;
- import javax.swing.JTextArea;
- import javax.swing.JTextField;
- import javax.swing.ListSelectionModel;
- import javax.swing.SwingUtilities;
- import javax.swing.UIManager;
- import javax.swing.table.DefaultTableModel;
-
- import ServerSide.Server;
-
- public class ServerUI {
- // 单例
- private static ServerUI serverUIInstance = null;
-
- public static synchronized ServerUI GetServerUI() {
- if (serverUIInstance == null) {
- serverUIInstance = new ServerUI();
- }
- return serverUIInstance;
- }
-
- private JFrame frmTcp;
- private JTextField textServerIP;
- private JTextField textPort;
- private JButton btnStart;
- private JButton btnStop;
- private JTextArea textAreaRecord;
- private JTable tblUsers;// 在线用户列表
-
- public JTextField GetTextServerIP() {
- return textServerIP;
- }
-
- public JTextField GetTextPort() {
- return textPort;
- }
-
- public JButton GetBtnStart() {
- return btnStart;
- }
-
- public JButton GetBtnStop() {
- return btnStop;
- }
-
- public JTextArea GetTextAreaRecord() {
- return textAreaRecord;
- }
-
- private ServerUI() {
- Init();
- }
-
- private void Init() {
- frmTcp = new JFrame();
- frmTcp.setResizable(false);
- frmTcp.setTitle("服务器界面");
- frmTcp.setBounds(100, 100, 700, 509);
- frmTcp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frmTcp.getContentPane().setLayout(null);
-
- // IP框
- JLabel lblip = new JLabel("服务器IP地址:");
- lblip.setBounds(10, 27, 105, 18);
- frmTcp.getContentPane().add(lblip);
- textServerIP = new JTextField();
- textServerIP.setText("0.0.0.0");
- textServerIP.setBounds(114, 24, 141, 24);
- frmTcp.getContentPane().add(textServerIP);
- textServerIP.setColumns(10);
- // 端口框
- JLabel label = new JLabel("端口号:");
- label.setBounds(293, 27, 72, 18);
- frmTcp.getContentPane().add(label);
- textPort = new JTextField();
- textPort.setText("6666");
- textPort.setBounds(356, 24, 86, 24);
- frmTcp.getContentPane().add(textPort);
- textPort.setColumns(10);
- // 开始按钮
- btnStart = new JButton("开始");
- btnStart.setBounds(479, 23, 95, 27);
- frmTcp.getContentPane().add(btnStart);
-
- // 启动按钮事件监听处理
- btnStart.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent arg0) {
- // 创建、启动服务器通信线程
- Thread serverThread = new Thread(new Server().new ServerThread());
- serverThread.start();
- }
- });
- // 停止按钮
- btnStop = new JButton("停止");
- btnStop.setEnabled(false);
- btnStop.setBounds(588, 23, 95, 27);
- frmTcp.getContentPane().add(btnStop);
-
- // 停止按钮事件监听处理
- btnStop.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent arg0) {
-
- }
-
- });
-
- JLabel label_1 = new JLabel("消息记录");
- label_1.setBounds(10, 58, 72, 18);
- frmTcp.getContentPane().add(label_1);
-
- JScrollPane scrollPane = new JScrollPane();
- scrollPane.setBounds(10, 78, 673, 159);
- frmTcp.getContentPane().add(scrollPane);
-
- textAreaRecord = new JTextArea();
- textAreaRecord.setBackground(Color.pink);
- textAreaRecord.setEditable(false);
- scrollPane.setViewportView(textAreaRecord);
-
- JLabel lblNewLabel = new JLabel("在线用户列表");
- lblNewLabel.setBounds(10, 250, 105, 18);
- frmTcp.getContentPane().add(lblNewLabel);
-
- JScrollPane scrollPane_1 = new JScrollPane();
- scrollPane_1.setBounds(10, 273, 673, 191);
- frmTcp.getContentPane().add(scrollPane_1);
-
- // 在线用户列表
- tblUsers = new JTable();
- tblUsers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- tblUsers.setModel(new DefaultTableModel(new Object[][] {}, new String[] { "序号", "用户名",
- "IP地址", "端口号", "登录时间" }) {
- private static final long serialVersionUID = 1L;
- boolean[] columnEditables = new boolean[] { true, true, true, false, true };
-
- public boolean isCellEditable(int row, int column) {
- return columnEditables[column];
- }
- });
- tblUsers.getColumnModel().getColumn(0).setPreferredWidth(56);
- tblUsers.getColumnModel().getColumn(1).setPreferredWidth(118);
- tblUsers.getColumnModel().getColumn(2).setPreferredWidth(126);
- tblUsers.getColumnModel().getColumn(3).setResizable(false);
- tblUsers.getColumnModel().getColumn(3).setPreferredWidth(61);
- tblUsers.getColumnModel().getColumn(4).setPreferredWidth(122);
- scrollPane_1.setViewportView(tblUsers);
-
- // 更换样式
- try {
- String style = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
- UIManager.setLookAndFeel(style);
- SwingUtilities.updateComponentTreeUI(this.frmTcp);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public static void main(String[] args) {
- ServerUI serverUI = ServerUI.GetServerUI();
- serverUI.frmTcp.setVisible(true);
- }
-
- }
5、ServerSide包里面
(1)Server代码
- package ServerSide;
-
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.net.SocketAddress;
- import java.util.HashMap;
- import ConnectMysql.OperatorMysql;
- import ServerGUI.ServerUI;
-
- public class Server {
- private static Server serverInstance=null;
- public static synchronized Server GetServer()
- {
- if(serverInstance==null)
- {
- serverInstance=new Server();
- }
- return serverInstance;
- }
-
-
-
- // 对数据库进行操作
- private static OperatorMysql operatorMysql = new OperatorMysql();
-
- private String userName;
- private String userPassword;
-
- ServerUI serverUI = ServerUI.GetServerUI();
- // 服务器套接字
- private ServerSocket server;
- // 服务器是否运行
- private boolean isRunning;
- // 用户名不能相同,存放每个用户和客户端套接字的映射。
- private HashMap<String, ClientHandler> clientHandlerMap = new HashMap<String, ClientHandler>();
-
- // 注册
- public Boolean Register(String userName, String userPassword) {
- if (operatorMysql.Search(userName)) {
- operatorMysql.Insert(userName, userPassword);
- this.userName = userName;
- this.userPassword = userPassword;
- return true;
- }
- return false;
- }
-
- // 登录
- public Boolean LogOn(String userName, String userPassword) {
- if (operatorMysql.Search(userName)) {
- return false;
- }
- return true;
- }
-
-
- // 内部类,服务器后台线程
- public class ServerThread implements Runnable {
- // 启动
- private void startServer() {
- try {
- // 获取serverIp 和 serverPort
- String serverIp = serverUI.GetTextServerIP().getText();
- int serverPort = Integer.parseInt(serverUI.GetTextPort().getText());
- // 创建套接字地址
- SocketAddress socketAddress = new InetSocketAddress(serverIp, serverPort);
- // 创建ServerSocket,绑定套接字地址
- server = new ServerSocket();
- server.bind(socketAddress);
- // 修改判断服务器是否运行的标识变量
- isRunning = true;
- // 修改启动和停止按钮状态
- serverUI.GetBtnStart().setEnabled(false);
- serverUI.GetBtnStop().setEnabled(true);
- addMsg("服务器启动成功");
- System.out.println("服务器启动成功");
-
- } catch (IOException e) {
- addMsg("服务器启动失败,请检查端口是否被占用");
- e.printStackTrace();
- isRunning = false;
- }
- }
-
- // 线程主体
- @Override
- public void run() {
- startServer();
- CloseServer();
- // 当服务器处于运行状态时,循环监听客户端的连接请求
- while (isRunning) {
- try {
-
- Socket socket = server.accept();
- // 创建与客户端交互的线程
- Thread thread = new Thread(new ClientHandler(socket));
- thread.start();
- } catch (IOException e) {
-
- }
- }
- }
-
- }
-
- public void CloseServer() {
- serverUI.GetBtnStop().addActionListener(new ActionListener() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- try {
- isRunning = false;
- server.close();
- clientHandlerMap.clear();
- // 修改按钮状态
- serverUI.GetBtnStart().setEnabled(true);
- serverUI.GetBtnStop().setEnabled(false);
- addMsg("服务器关闭成功");
- } catch (IOException e1) {
- e1.printStackTrace();
- }
- }
- });
- }
-
- // 添加消息到文本框textAreaRecord
- private void addMsg(String msg) {
- // 在文本区中添加一条消息,并加上换行
- serverUI.GetTextAreaRecord().append(msg + "\n");
- // 自动滚动到文本区的最后一行
- serverUI.GetTextAreaRecord().setCaretPosition(serverUI.GetTextAreaRecord().getText().length());
-
- }
-
- //更新服务器在线用户表
- public void UpdateUserTbl() {
-
- }
-
- //获取IP地址
- public Object GetInetAddress() {
-
- return null;
- }
- //获取端口号
- public int GetPort()
- {
- return 6666;
- }
-
- // 内部类,用于和客户端交互
- class ClientHandler implements Runnable {
- private Socket socket;
- private DataInputStream dis;
- private DataOutputStream dos;
- private boolean isConnected;
- private String username;
-
- public ClientHandler(Socket socket) {
- this.socket = socket;
- try {
- this.dis = new DataInputStream(socket.getInputStream());
- this.dos = new DataOutputStream(socket.getOutputStream());
- isConnected = true;
- } catch (IOException e) {
- isConnected = false;
- e.printStackTrace();
- }
- }
-
- @Override
- public void run() {
- while (isRunning && isConnected) {
- try {
- // 读取客户端发送的报文
- String msg = dis.readUTF();
- String[] parts = msg.split("#");
- switch (parts[0]) {
- // 处理登录报文
- case "CONNECT":
- String connectUsername = parts[1];
- // 如果该用户名已登录,则返回失败报文,否则返回成功报文
- if (clientHandlerMap.containsKey(connectUsername)) {
- dos.writeUTF("FAIL");
- } else {
- dos.writeUTF("SUCCESS");
- // 将此客户端处理线程的信息添加到clientHandlerMap中
- clientHandlerMap.put(connectUsername, this);
- // 将现有用户的信息发给新用户
- StringBuffer msgUserList = new StringBuffer();
- msgUserList.append("USERLIST#");
- for (String username : clientHandlerMap.keySet()) {
- msgUserList.append(username + "#");
- }
- dos.writeUTF(msgUserList.toString());
- // 将新登录的用户信息广播给其他用户
- String msgLogin = "CONNECT#" + connectUsername;
- BroadcastMsg(connectUsername, msgLogin);
- // 存储登录的用户名
- this.username = connectUsername;
- UpdateUserTbl();// 未实现
- }
- break;
- // 处理退出报文
- case "DISCONNECT":
- clientHandlerMap.remove(username);
- String msgLogout = "DISCONNECT#" + username;
- BroadcastMsg(username, msgLogout);
- isConnected = false;
- dis.close();
- dos.close();
- socket.close();
- UpdateUserTbl();
- break;
- case "TALKTO_ALL":
- String msgTalkToAll = "TALKTO_ALL#" + username + "#" + parts[1];
- BroadcastMsg(username, msgTalkToAll);
- break;
- case "TALKTO":
- ClientHandler clientHandler = clientHandlerMap.get(parts[1]);
- if (null != clientHandler) {
- String msgTalkTo = "TALKTO#" + username + "#" + parts[2];
- clientHandler.dos.writeUTF(msgTalkTo);
- clientHandler.dos.flush();
- }
-
- default:
- break;
- }
- } catch (IOException e) {
- isConnected = false;
- e.printStackTrace();
- }
- }
- }
-
- // 将某个用户发来的消息广播给其它用户
- private void BroadcastMsg(String fromUsername, String msg) throws IOException {
- for (String toUserName : clientHandlerMap.keySet()) {
- if (fromUsername.equals(toUserName) == false) {
- DataOutputStream dos = clientHandlerMap.get(toUserName).dos;
- dos.writeUTF(msg);
- dos.flush();
- }
- }
- }
-
- }
- }
6、Utils包里面
(1)Utils代码
- package Utils;
-
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.IOException;
- import java.net.Socket;
-
-
- import javax.swing.JTextArea;
-
- public class Utils {
- // 通过套接字S发送字符串
- public static void sendMsg(Socket s, String msg) {
- try {
- // 字符流
- DataOutputStream dos = new DataOutputStream(s.getOutputStream());
- dos.writeUTF(msg);
- dos.flush();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- // 在套接字S上读取字符串,如果TCP连接关闭,返回null
- public static String recvMsg(Socket s) throws IOException {
- String msg = null;
- DataInputStream dis = (DataInputStream) new DataInputStream(s.getInputStream());
- msg = ((DataInputStream) dis).readUTF();
- return msg;
-
- }
-
- // 添加消息到文本记录框JTextArea,并且滚动显示到最后一行
- public static void addMsgRec(JTextArea textArea, String msg) {
- textArea.append(msg + "\n");
- textArea.setCaretPosition(textArea.getText().length());
- }
- }
最后添加一个Mysql的库文件就可以连接数据库了。
测试如下:
首先,打开mysql数据库,然后启动服务器启动成功,如下图。
然后启动登录界面,如下图:
点击注册按钮,进入注册界面,如下图:
进行注册,如果注册成功就会进行注册成功提示,如下图:
如果用户名已经注册就会进行注册失败提示,如下图:
点击返回按钮进入登录界面进行登录,如果用户名不存在会提示登录失败,如下图:
如果不输入任何东西点击登录也会提示用户进行输入,如下图:
登录成功以后就进入客户端主界面,如下图:
界面上有在线用户和上线提示。
然后通过重复前面的步骤在开两个客户端,此时界面,如下图:
然后就可以进行聊天了,首先默认的是群聊,如下图:
群聊正常的实现了。
私聊主要就是选择私聊按钮,然后选择想要私聊的用户,如果不选择私聊用户,就会进行提醒,如下图:‘
选择在线用户后就可以进行私聊了,如下图:
正常实现了,不过这里还有一个问题就是如果选择自己的话也能进行私聊,这就不对了,如下图:
因为时间原因,服务器端没有全部进行完善,还有一部分功能没有实现,如下图:
源代码下载:下载链接
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。