当前位置:   article > 正文

Java实现私聊和群聊功能之美_javasocket窗口群聊和私聊

javasocket窗口群聊和私聊

工程构成如下图:

1、ClientGUI包里面

(1)LogOn.java代码如下:

  1. package ClientGUI;
  2. import java.awt.BorderLayout;
  3. import java.awt.FlowLayout;
  4. import java.awt.GridLayout;
  5. import java.awt.event.ActionEvent;
  6. import java.awt.event.ActionListener;
  7. import javax.swing.JButton;
  8. import javax.swing.JFrame;
  9. import javax.swing.JLabel;
  10. import javax.swing.JOptionPane;
  11. import javax.swing.JPanel;
  12. import javax.swing.JPasswordField;
  13. import javax.swing.JTextField;
  14. import javax.swing.SwingUtilities;
  15. import javax.swing.UIManager;
  16. import ClientSide.Client;
  17. import ClientSide.Client.ClientThread;
  18. import ServerSide.Server;
  19. //登录窗口
  20. public class LogOn extends JFrame implements ActionListener {
  21. private Register register;
  22. private ClientThread clientThread;
  23. private Server server=Server.GetServer();
  24. private JLabel jlUserName;
  25. private JLabel jlPassword;
  26. private JTextField jtUserName;
  27. private JPasswordField jpPassword;
  28. private JButton jbLogOn;
  29. private JButton jbRegister;
  30. private JPanel jpDown;
  31. private JPanel jpCenter;
  32. public LogOn() {
  33. Init();
  34. }
  35. private void Init() {
  36. jlUserName = new JLabel("用户名");
  37. jlPassword = new JLabel("密 码");
  38. jtUserName = new JTextField(15);
  39. jpPassword = new JPasswordField(15);
  40. jbLogOn = new JButton("登录");
  41. jbRegister = new JButton("注册");
  42. jbLogOn.addActionListener(this);
  43. jbRegister.addActionListener(this);
  44. jpCenter = new JPanel();
  45. jpCenter.setLayout(new GridLayout(2, 2));
  46. jpCenter.add(jlUserName);
  47. jpCenter.add(jtUserName);
  48. jpCenter.add(jlPassword);
  49. jpCenter.add(jpPassword);
  50. jpDown = new JPanel();
  51. jpDown.setLayout(new FlowLayout());
  52. jpDown.add(jbLogOn);
  53. jpDown.add(jbRegister);
  54. this.setLayout(new BorderLayout());
  55. this.add("Center", jpCenter);
  56. this.add("South", jpDown);
  57. this.setTitle("用户登录界面");
  58. this.setSize(350, 150);
  59. this.setLocationRelativeTo(null);
  60. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  61. this.setVisible(true);
  62. // 更改窗体样式
  63. try {
  64. String style = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
  65. UIManager.setLookAndFeel(style);
  66. SwingUtilities.updateComponentTreeUI(this);
  67. } catch (Exception e) {
  68. e.printStackTrace();
  69. }
  70. }
  71. @Override
  72. public void actionPerformed(ActionEvent e) {
  73. Object source = e.getSource();
  74. if (source == jbLogOn) {
  75. //判断是否为空
  76. if(jtUserName.getText()==null || jtUserName.getText().equals("")
  77. || String.valueOf(jpPassword.getPassword())==null ||
  78. String.valueOf(jpPassword.getPassword()).equals(""))
  79. {
  80. JOptionPane.showMessageDialog(null, "请输入账号或者密码");
  81. }else
  82. {
  83. if(server.LogOn(jtUserName.getText(), String.valueOf(jpPassword.getPassword())))
  84. {
  85. MainUI mainUI=new MainUI(jtUserName.getText());
  86. Client client=Client.GetClient();
  87. client.SetMainUI(mainUI);
  88. client.SetUserName(mainUI.GetUserName());
  89. clientThread=client.new ClientThread();
  90. client.SetClientThread(clientThread);
  91. clientThread.start();
  92. this.setVisible(false);
  93. }else
  94. {
  95. JOptionPane.showMessageDialog(null, "账号或者密码错误");
  96. }
  97. }
  98. } else if (source == jbRegister) {
  99. register=new Register(this);
  100. this.setVisible(false);
  101. }
  102. }
  103. public static void main(String[] args) {
  104. new LogOn();
  105. }
  106. }

(2)MainUI代码如下:

  1. package ClientGUI;
  2. import java.awt.Color;
  3. import java.awt.event.ActionEvent;
  4. import java.awt.event.ActionListener;
  5. import javax.swing.ButtonGroup;
  6. import javax.swing.DefaultListModel;
  7. import javax.swing.JButton;
  8. import javax.swing.JFrame;
  9. import javax.swing.JLabel;
  10. import javax.swing.JList;
  11. import javax.swing.JRadioButton;
  12. import javax.swing.JScrollPane;
  13. import javax.swing.JTextArea;
  14. import javax.swing.JTextField;
  15. import javax.swing.ListSelectionModel;
  16. import javax.swing.SwingUtilities;
  17. import javax.swing.UIManager;
  18. import ClientSide.Client;
  19. public class MainUI{
  20. // private static MainUI mainUIInstance=null;
  21. //
  22. // public static synchronized MainUI GetMainUI()
  23. // {
  24. // if(mainUIInstance==null)
  25. // {
  26. // mainUIInstance=new MainUI();
  27. // }
  28. // return mainUIInstance;
  29. // }
  30. //
  31. private JFrame frmtcp;
  32. private JTextField textServerIP;// IP
  33. private JTextField textServerPort;// 端口
  34. private JTextArea textAreaRecord;// 消息文本记录框
  35. private JButton btnSend;// 发送按钮
  36. private JButton btnQuit;// 退出按钮
  37. private JLabel jlUsername;// 用户名
  38. private JList<String> listUsers;// 用户列表 Jlist控件显示客户端的用户列表。数据保存在DefaultListmodel数据模型对象中。
  39. private final ButtonGroup buttonGroup = new ButtonGroup();
  40. private JRadioButton rdbtnBrocast;// 群聊
  41. private JRadioButton rdbtnPrivateChat;// 私聊
  42. private JTextArea textAreaMsg;// 消息框
  43. private DefaultListModel<String> modelUsers;// 数据模型,用于更新数据
  44. public JTextField GetTextServerIP()
  45. {
  46. return textServerIP;
  47. }
  48. public JTextField GetTextServerPort()
  49. {
  50. return textServerPort;
  51. }
  52. public void SetUserName(String userName)
  53. {
  54. jlUsername.setText(userName);
  55. }
  56. public String GetUserName()
  57. {
  58. return jlUsername.getText();
  59. }
  60. public JTextArea GetTextAreaMsg()
  61. {
  62. return textAreaMsg;
  63. }
  64. public JButton GetBtnQuit()
  65. {
  66. return btnQuit;
  67. }
  68. public JButton GetBtnSend()
  69. {
  70. return btnSend;
  71. }
  72. public JList<String> GetListUsers()
  73. {
  74. return listUsers;
  75. }
  76. public DefaultListModel<String> GetModelUsers()
  77. {
  78. return modelUsers;
  79. }
  80. public JRadioButton GetRdbtnBrocast()
  81. {
  82. return rdbtnBrocast;
  83. }
  84. public JRadioButton GetRdbtnPrivateChat()
  85. {
  86. return rdbtnPrivateChat;
  87. }
  88. public JTextArea GetTextAreaRecord()
  89. {
  90. return textAreaRecord;
  91. }
  92. public JFrame GetJfrmtcp()
  93. {
  94. return frmtcp;
  95. }
  96. public MainUI(String userName)
  97. {
  98. Init(userName);
  99. modelUsers = new DefaultListModel();
  100. modelUsers = new DefaultListModel<String>();
  101. listUsers.setModel(modelUsers);
  102. }
  103. private void Init(String userName)
  104. {
  105. frmtcp = new JFrame();
  106. frmtcp.setResizable(false);
  107. frmtcp.setTitle("聊天主界面");
  108. frmtcp.setBounds(100, 100, 715, 476);
  109. frmtcp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  110. frmtcp.getContentPane().setLayout(null);
  111. frmtcp.setVisible(true);
  112. // IP
  113. JLabel lblNewLabel = new JLabel("服务器IP地址:");
  114. lblNewLabel.setBounds(14, 24, 121, 18);
  115. frmtcp.getContentPane().add(lblNewLabel);
  116. textServerIP = new JTextField();
  117. textServerIP.setText("127.0.0.1");
  118. textServerIP.setBounds(121, 21, 121, 24);
  119. frmtcp.getContentPane().add(textServerIP);
  120. textServerIP.setColumns(10);
  121. // 端口
  122. JLabel lblNewLabel_1 = new JLabel("端口号:");
  123. lblNewLabel_1.setBounds(256, 24, 58, 18);
  124. frmtcp.getContentPane().add(lblNewLabel_1);
  125. textServerPort = new JTextField();
  126. textServerPort.setText("6666");
  127. textServerPort.setBounds(313, 21, 48, 24);
  128. frmtcp.getContentPane().add(textServerPort);
  129. textServerPort.setColumns(10);
  130. // 用户名
  131. JLabel label_1 = new JLabel("用户名:");
  132. label_1.setBounds(375, 24, 58, 18);
  133. frmtcp.getContentPane().add(label_1);
  134. jlUsername = new JLabel(userName);
  135. jlUsername.setBounds(433, 21, 95, 24);
  136. frmtcp.getContentPane().add(jlUsername);
  137. //退出按钮
  138. btnQuit = new JButton("退出");
  139. btnQuit.setBounds(596, 20, 95, 27);
  140. frmtcp.getContentPane().add(btnQuit);
  141. btnQuit.addActionListener(new ActionListener() {
  142. @Override
  143. public void actionPerformed(ActionEvent arg0) {
  144. }
  145. });
  146. // 发送按钮
  147. btnSend = new JButton("发送");
  148. btnSend.setEnabled(false);
  149. btnSend.setBounds(444, 409, 88, 27);
  150. frmtcp.getContentPane().add(btnSend);
  151. // 连接按钮事件处理程序
  152. btnSend.addActionListener(new ActionListener() {
  153. @Override
  154. public void actionPerformed(ActionEvent arg0) {
  155. }
  156. });
  157. // 聊天记录框
  158. JLabel label = new JLabel("聊天区");
  159. label.setBounds(14, 55, 72, 18);
  160. frmtcp.getContentPane().add(label);
  161. JScrollPane scrollPane = new JScrollPane();
  162. scrollPane.setBounds(14, 72, 518, 228);
  163. frmtcp.getContentPane().add(scrollPane);
  164. textAreaRecord = new JTextArea();
  165. textAreaRecord.setBackground(Color.pink);
  166. textAreaRecord.setEditable(false);
  167. scrollPane.setViewportView(textAreaRecord);
  168. // 消息输入框
  169. JScrollPane scrollPane_1 = new JScrollPane();
  170. scrollPane_1.setBounds(14, 332, 518, 73);
  171. frmtcp.getContentPane().add(scrollPane_1);
  172. textAreaMsg = new JTextArea();
  173. scrollPane_1.setViewportView(textAreaMsg);
  174. JLabel label_2 = new JLabel("在线用户");
  175. label_2.setBounds(543, 55, 72, 18);
  176. frmtcp.getContentPane().add(label_2);
  177. // 用户列表框
  178. JScrollPane scrollPane_2 = new JScrollPane();
  179. scrollPane_2.setBounds(546, 72, 149, 334);
  180. frmtcp.getContentPane().add(scrollPane_2);
  181. listUsers = new JList<String>();
  182. listUsers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  183. scrollPane_2.setViewportView(listUsers);
  184. rdbtnBrocast = new JRadioButton("群聊");
  185. buttonGroup.add(rdbtnBrocast);
  186. rdbtnBrocast.setBounds(66, 306, 104, 22);
  187. frmtcp.getContentPane().add(rdbtnBrocast);
  188. rdbtnBrocast.setSelected(true);
  189. rdbtnPrivateChat = new JRadioButton("私聊");
  190. buttonGroup.add(rdbtnPrivateChat);
  191. //rdbtnPrivateChat.setSelected(true);
  192. rdbtnPrivateChat.setBounds(192, 306, 72, 22);
  193. frmtcp.getContentPane().add(rdbtnPrivateChat);
  194. // 更换样式
  195. try {
  196. String style = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
  197. UIManager.setLookAndFeel(style);
  198. // 更新窗体样式
  199. SwingUtilities.updateComponentTreeUI(this.frmtcp);
  200. } catch (Exception e) {
  201. e.printStackTrace();
  202. }
  203. }
  204. }

(3)Register代码如下:

  1. package ClientGUI;
  2. import java.awt.BorderLayout;
  3. import java.awt.FlowLayout;
  4. import java.awt.GridLayout;
  5. import java.awt.event.ActionEvent;
  6. import java.awt.event.ActionListener;
  7. import javax.swing.JButton;
  8. import javax.swing.JFrame;
  9. import javax.swing.JLabel;
  10. import javax.swing.JOptionPane;
  11. import javax.swing.JPanel;
  12. import javax.swing.JPasswordField;
  13. import javax.swing.JTextField;
  14. import javax.swing.SwingUtilities;
  15. import javax.swing.UIManager;
  16. import ClientSide.Client;
  17. import ServerSide.Server;
  18. //注册窗口
  19. public class Register extends JFrame implements ActionListener {
  20. private LogOn logOn;
  21. private JLabel jlUserName;
  22. private JLabel jlPassword;
  23. private JTextField jtUserName;
  24. public JTextField GetJtUserName()
  25. {
  26. return jtUserName;
  27. }
  28. private JPasswordField jpPassword;
  29. private JButton jbreturn;
  30. private JButton jbRegister;
  31. private JPanel jpDown;
  32. private JPanel jpCenter;
  33. private Server server = Server.GetServer();
  34. public Register(LogOn logOn) {
  35. Init(logOn);
  36. }
  37. private void Init(LogOn logOn) {
  38. this.logOn=logOn;
  39. jlUserName = new JLabel("用户名");
  40. jlPassword = new JLabel("密 码");
  41. jtUserName = new JTextField(15);
  42. jpPassword = new JPasswordField(15);
  43. jbreturn = new JButton("返回");
  44. jbRegister = new JButton("注册");
  45. jbreturn.addActionListener(this);
  46. jbRegister.addActionListener(this);
  47. jpCenter = new JPanel();
  48. jpCenter.setLayout(new GridLayout(2, 2));
  49. jpCenter.add(jlUserName);
  50. jpCenter.add(jtUserName);
  51. jpCenter.add(jlPassword);
  52. jpCenter.add(jpPassword);
  53. jpDown = new JPanel();
  54. jpDown.setLayout(new FlowLayout());
  55. jpDown.add(jbRegister);
  56. jpDown.add(jbreturn);
  57. this.setLayout(new BorderLayout());
  58. this.add("Center", jpCenter);
  59. this.add("South", jpDown);
  60. this.setTitle("用户注册界面");
  61. this.setSize(350, 150);
  62. this.setLocationRelativeTo(null);
  63. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  64. this.setVisible(true);
  65. // 更改窗体样式
  66. try {
  67. String style = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
  68. UIManager.setLookAndFeel(style);
  69. SwingUtilities.updateComponentTreeUI(this);
  70. } catch (Exception e) {
  71. e.printStackTrace();
  72. }
  73. }
  74. @Override
  75. public void actionPerformed(ActionEvent e) {
  76. Object source = e.getSource();
  77. if (source == jbreturn) {
  78. logOn.setVisible(true);
  79. this.setVisible(false);
  80. } else if (source == jbRegister) {
  81. // 判断是否为空
  82. if (jtUserName.getText() == null || jtUserName.getText().equals("")
  83. || String.valueOf(jpPassword.getPassword()) == null
  84. || String.valueOf(jpPassword.getPassword()).equals("")) {
  85. JOptionPane.showMessageDialog(null, "请输入账号和密码");
  86. } else {
  87. // 数据传给服务器进行注册
  88. if (server.Register(jtUserName.getText(), String.valueOf(jpPassword.getPassword()))) {
  89. JOptionPane.showMessageDialog(null, "注册成功");
  90. }else {
  91. JOptionPane.showMessageDialog(null, "注册失败,改用户名已注册");
  92. }
  93. }
  94. }
  95. }
  96. }

2、ClientSide包里面

(1)Client代码如下:

  1. package ClientSide;
  2. import java.awt.Component;
  3. import java.awt.event.ActionEvent;
  4. import java.awt.event.ActionListener;
  5. import java.io.DataInputStream;
  6. import java.io.DataOutputStream;
  7. import java.io.IOException;
  8. import java.net.Socket;
  9. import javax.swing.JButton;
  10. import javax.swing.JList;
  11. import javax.swing.JOptionPane;
  12. import ClientGUI.MainUI;
  13. import ClientGUI.Register;
  14. import Utils.Utils;
  15. public class Client{
  16. private static Client clientInstance=null;
  17. public static synchronized Client GetClient()
  18. {
  19. if(clientInstance==null)
  20. {
  21. clientInstance=new Client();
  22. }
  23. return clientInstance;
  24. }
  25. private MainUI mainUI;
  26. public void SetMainUI(MainUI mainUI)
  27. {
  28. this.mainUI=mainUI;
  29. }
  30. private ClientThread clientThread;
  31. public void SetClientThread(ClientThread clientThread)
  32. {
  33. if(clientThread!=null)
  34. {
  35. this.clientThread=clientThread;
  36. }
  37. }
  38. private String username;
  39. public void SetUserName(String userName)
  40. {
  41. this.username=userName;
  42. }
  43. // 内部类.客户端线程,负责与服务器交互
  44. public class ClientThread extends Thread{
  45. private final Component frmtcp = null;
  46. // 通信套接字
  47. private Socket socket;
  48. // 基本数据输入流
  49. private DataInputStream dis;
  50. // 基本数据输出流
  51. private DataOutputStream dos;
  52. // 是否登录
  53. private boolean isLogged;
  54. // 连接服务器
  55. public void ConnectServer() {
  56. // 获取服务器IP地址和端口
  57. String serverIp = mainUI.GetTextServerIP().getText();
  58. int serverPort = Integer.parseInt(mainUI.GetTextServerPort().getText());
  59. try {
  60. // 连接服务器,获取套接字IO流
  61. socket = new Socket(serverIp, serverPort);
  62. dis = new DataInputStream(socket.getInputStream());
  63. dos = new DataOutputStream(socket.getOutputStream());
  64. // 获取用户名,构建、发送登录报文
  65. //String username = mainUI.GetUserName();
  66. String msgConnect = "CONNECT#" + username;
  67. dos.writeUTF(msgConnect);
  68. dos.flush();
  69. // 读取服务器返回的信息,判断是否登录成功
  70. String response = dis.readUTF();
  71. // 登录失败
  72. if (response.equals("FAIL")) {
  73. addMsg("username+连接服务器失败");
  74. dis.close();
  75. dos.close();
  76. socket.close();
  77. return;
  78. } else {
  79. addMsg(username+"上线了!");
  80. isLogged = true;
  81. mainUI.GetBtnQuit().setText("退出");
  82. mainUI.GetBtnSend().setEnabled(true);
  83. String[] self = { username };
  84. UpdateJList(mainUI.GetListUsers(), self, "ADD");
  85. }
  86. } catch (IOException e) {
  87. e.printStackTrace();
  88. }
  89. }
  90. // 退出聊天室功能实现
  91. public void DisConnectServer() {
  92. try {
  93. Utils.sendMsg(socket, "DISCONNECT#" + username);
  94. mainUI.GetModelUsers().clear();
  95. mainUI.GetListUsers().setModel(mainUI.GetModelUsers());
  96. addMsg(username+"下线了");
  97. isLogged=false;
  98. mainUI.GetBtnQuit().setEnabled(false);
  99. mainUI.GetBtnSend().setEnabled(false);
  100. String[] self = { username };
  101. UpdateJList(mainUI.GetListUsers(), self, "DEL");
  102. dis.close();
  103. dos.close();
  104. socket.close();
  105. clientThread.interrupt();
  106. } catch (IOException e) {
  107. e.printStackTrace();
  108. }
  109. }
  110. // 更新用户列表
  111. public void UpdateJList(JList jList, String[] items, String op) {
  112. switch (op) {
  113. case "ADD": // 添加新数据
  114. for (int i = 0; i < items.length; ++i) {
  115. mainUI.GetModelUsers().addElement(items[i]);
  116. break;
  117. }
  118. case "DEL":// 删除数据
  119. for (int i = 0; i < items.length; ++i) {
  120. mainUI.GetModelUsers().removeElement(items[i]);
  121. break;
  122. }
  123. default:
  124. break;
  125. }
  126. jList.setModel(mainUI.GetModelUsers());// 更新数据
  127. }
  128. // 发送消息
  129. public void SendChatMsg() {
  130. String msgChat = null;
  131. String dstUser = "所有人";
  132. if (mainUI.GetRdbtnBrocast().isSelected()) {
  133. msgChat = "TALKTO_ALL#" + mainUI.GetTextAreaMsg().getText();
  134. }
  135. if (mainUI.GetRdbtnPrivateChat().isSelected()) {
  136. dstUser = (String) mainUI.GetListUsers().getSelectedValue();
  137. if (dstUser == null) {
  138. JOptionPane.showMessageDialog(this.frmtcp, "请选择需要私聊的用户!");
  139. return;
  140. }
  141. msgChat = "TALKTO#" + dstUser + "#" + mainUI.GetTextAreaMsg().getText();
  142. }
  143. // 发送聊天报文到服务器
  144. Utils.sendMsg(socket, msgChat);
  145. // 添加到消息记录框
  146. addMsg(" 我对" + dstUser + "说:" + mainUI.GetTextAreaMsg().getText());
  147. // if (null != msgChat) {
  148. // try {
  149. // dos.writeUTF(msgChat);
  150. // dos.flush();
  151. // } catch (IOException e) {
  152. // e.printStackTrace();
  153. // }
  154. // }
  155. }
  156. // 线程主体
  157. @Override
  158. public void run() {
  159. ConnectServer();
  160. //发送消息按钮
  161. mainUI.GetBtnSend().addActionListener(new ActionListener() {
  162. @Override
  163. public void actionPerformed(ActionEvent e) {
  164. SendChatMsg();
  165. }
  166. });
  167. //退出按钮
  168. mainUI.GetBtnQuit().addActionListener(new ActionListener() {
  169. @Override
  170. public void actionPerformed(ActionEvent e) {
  171. DisConnectServer();
  172. }
  173. });
  174. //消息处理
  175. while (isLogged) {
  176. try {
  177. String msg = dis.readUTF();
  178. String[] parts = msg.split("#");
  179. switch (parts[0]) {
  180. // 处理服务器发来的用户列表报文
  181. case "USERLIST":
  182. String[] self = { username };
  183. UpdateJList(mainUI.GetListUsers(), self, "ADD");
  184. for (int i = 1; i < parts.length; i++) {
  185. mainUI.GetModelUsers().addElement(parts[i]);
  186. }
  187. break;
  188. // 处理服务器发来的新用户连接表报文
  189. case "CONNECT":
  190. mainUI.GetModelUsers().addElement(parts[1]);
  191. addMsg(" " + parts[1] + "上线了");
  192. break;
  193. case "DISCONNECT":
  194. mainUI.GetModelUsers().removeElement(parts[1]);
  195. addMsg(" " + parts[1] + "下线了");
  196. break;
  197. case "TALKTO_ALL":
  198. addMsg(parts[1] + " 跟所有人说:" + parts[2]);
  199. break;
  200. case "TALKTO":
  201. addMsg(parts[1] + " 跟我说:" + parts[2]);
  202. break;
  203. default:
  204. break;
  205. }
  206. } catch (IOException e) {
  207. isLogged = false;
  208. e.printStackTrace();
  209. }
  210. }
  211. }
  212. // 添加消息到文本框textAreaRecord
  213. public void addMsg(String msg) {
  214. // 在文本区中添加一条消息,并加上换行
  215. mainUI.GetTextAreaRecord().append(msg + "\n");
  216. // 自动滚动到文本区的最后一行
  217. mainUI.GetTextAreaRecord().setCaretPosition(mainUI.GetTextAreaRecord().getText().length());
  218. }
  219. }
  220. }

3、ConnectMysql包里面

(1)Connect代码如下:

  1. package ConnectMysql;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.PreparedStatement;
  5. import java.sql.ResultSet;
  6. import java.sql.SQLException;
  7. public class Connect {
  8. private Connection con;
  9. public Connection GetConnection() {
  10. try {
  11. Class.forName("com.mysql.cj.jdbc.Driver");
  12. System.out.println("数据库驱动加载成功");
  13. } catch (ClassNotFoundException e) {
  14. e.printStackTrace();
  15. }
  16. try {
  17. con = DriverManager.getConnection("jdbc:mysql://localhost:3306/student?useSSL=false&serverTimezone=UTC",
  18. "root", "249913");
  19. System.out.println("数据库连接成功");
  20. } catch (SQLException e) {
  21. e.printStackTrace();
  22. }
  23. return con;
  24. }
  25. //关闭数据库
  26. public void CloseConn(ResultSet rs, PreparedStatement pstm, Connection conn) throws Exception {
  27. if (rs != null) {
  28. rs.close();
  29. }
  30. if (pstm != null) {
  31. pstm.close();
  32. }
  33. if (conn != null) {
  34. conn.close();
  35. }
  36. }
  37. }

(2)OperatorMysql代码如下

  1. package ConnectMysql;
  2. import java.sql.Connection;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. public class OperatorMysql {
  7. Connect connect = new Connect();
  8. private Connection con;
  9. // 增加数据(增加数据前先查询用户名是否已存在)
  10. public void Insert(String userName, String userPassword) {
  11. con = connect.GetConnection();
  12. PreparedStatement pstm = null;
  13. String sql_insert = "insert into user(userName,userPassword) values(?,?)";
  14. try {
  15. pstm = con.prepareStatement(sql_insert);
  16. pstm.setString(1, userName);
  17. pstm.setString(2, userPassword);
  18. pstm.executeUpdate();
  19. connect.CloseConn(null, pstm, con);
  20. } catch (SQLException e) {
  21. e.printStackTrace();
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. // 查找数据(用户名重复返回false)
  27. public Boolean Search(String userName) {
  28. con = connect.GetConnection();
  29. PreparedStatement pstm = null;
  30. ResultSet rs = null;
  31. String sql_Search = "select *from user where userName=?";
  32. try {
  33. pstm = con.prepareStatement(sql_Search);
  34. pstm.setString(1, userName);
  35. rs = pstm.executeQuery();
  36. if(rs.next())
  37. {
  38. return false;
  39. }
  40. } catch (SQLException e) {
  41. e.printStackTrace();
  42. }
  43. return true;
  44. }
  45. }

4、ServerGUI包里面

(1)ServerUI代码如下:

  1. package ServerGUI;
  2. import java.awt.Color;
  3. import java.awt.event.ActionEvent;
  4. import java.awt.event.ActionListener;
  5. import java.io.IOException;
  6. import javax.swing.JButton;
  7. import javax.swing.JFrame;
  8. import javax.swing.JLabel;
  9. import javax.swing.JScrollPane;
  10. import javax.swing.JTable;
  11. import javax.swing.JTextArea;
  12. import javax.swing.JTextField;
  13. import javax.swing.ListSelectionModel;
  14. import javax.swing.SwingUtilities;
  15. import javax.swing.UIManager;
  16. import javax.swing.table.DefaultTableModel;
  17. import ServerSide.Server;
  18. public class ServerUI {
  19. // 单例
  20. private static ServerUI serverUIInstance = null;
  21. public static synchronized ServerUI GetServerUI() {
  22. if (serverUIInstance == null) {
  23. serverUIInstance = new ServerUI();
  24. }
  25. return serverUIInstance;
  26. }
  27. private JFrame frmTcp;
  28. private JTextField textServerIP;
  29. private JTextField textPort;
  30. private JButton btnStart;
  31. private JButton btnStop;
  32. private JTextArea textAreaRecord;
  33. private JTable tblUsers;// 在线用户列表
  34. public JTextField GetTextServerIP() {
  35. return textServerIP;
  36. }
  37. public JTextField GetTextPort() {
  38. return textPort;
  39. }
  40. public JButton GetBtnStart() {
  41. return btnStart;
  42. }
  43. public JButton GetBtnStop() {
  44. return btnStop;
  45. }
  46. public JTextArea GetTextAreaRecord() {
  47. return textAreaRecord;
  48. }
  49. private ServerUI() {
  50. Init();
  51. }
  52. private void Init() {
  53. frmTcp = new JFrame();
  54. frmTcp.setResizable(false);
  55. frmTcp.setTitle("服务器界面");
  56. frmTcp.setBounds(100, 100, 700, 509);
  57. frmTcp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  58. frmTcp.getContentPane().setLayout(null);
  59. // IP框
  60. JLabel lblip = new JLabel("服务器IP地址:");
  61. lblip.setBounds(10, 27, 105, 18);
  62. frmTcp.getContentPane().add(lblip);
  63. textServerIP = new JTextField();
  64. textServerIP.setText("0.0.0.0");
  65. textServerIP.setBounds(114, 24, 141, 24);
  66. frmTcp.getContentPane().add(textServerIP);
  67. textServerIP.setColumns(10);
  68. // 端口框
  69. JLabel label = new JLabel("端口号:");
  70. label.setBounds(293, 27, 72, 18);
  71. frmTcp.getContentPane().add(label);
  72. textPort = new JTextField();
  73. textPort.setText("6666");
  74. textPort.setBounds(356, 24, 86, 24);
  75. frmTcp.getContentPane().add(textPort);
  76. textPort.setColumns(10);
  77. // 开始按钮
  78. btnStart = new JButton("开始");
  79. btnStart.setBounds(479, 23, 95, 27);
  80. frmTcp.getContentPane().add(btnStart);
  81. // 启动按钮事件监听处理
  82. btnStart.addActionListener(new ActionListener() {
  83. @Override
  84. public void actionPerformed(ActionEvent arg0) {
  85. // 创建、启动服务器通信线程
  86. Thread serverThread = new Thread(new Server().new ServerThread());
  87. serverThread.start();
  88. }
  89. });
  90. // 停止按钮
  91. btnStop = new JButton("停止");
  92. btnStop.setEnabled(false);
  93. btnStop.setBounds(588, 23, 95, 27);
  94. frmTcp.getContentPane().add(btnStop);
  95. // 停止按钮事件监听处理
  96. btnStop.addActionListener(new ActionListener() {
  97. @Override
  98. public void actionPerformed(ActionEvent arg0) {
  99. }
  100. });
  101. JLabel label_1 = new JLabel("消息记录");
  102. label_1.setBounds(10, 58, 72, 18);
  103. frmTcp.getContentPane().add(label_1);
  104. JScrollPane scrollPane = new JScrollPane();
  105. scrollPane.setBounds(10, 78, 673, 159);
  106. frmTcp.getContentPane().add(scrollPane);
  107. textAreaRecord = new JTextArea();
  108. textAreaRecord.setBackground(Color.pink);
  109. textAreaRecord.setEditable(false);
  110. scrollPane.setViewportView(textAreaRecord);
  111. JLabel lblNewLabel = new JLabel("在线用户列表");
  112. lblNewLabel.setBounds(10, 250, 105, 18);
  113. frmTcp.getContentPane().add(lblNewLabel);
  114. JScrollPane scrollPane_1 = new JScrollPane();
  115. scrollPane_1.setBounds(10, 273, 673, 191);
  116. frmTcp.getContentPane().add(scrollPane_1);
  117. // 在线用户列表
  118. tblUsers = new JTable();
  119. tblUsers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  120. tblUsers.setModel(new DefaultTableModel(new Object[][] {}, new String[] { "序号", "用户名",
  121. "IP地址", "端口号", "登录时间" }) {
  122. private static final long serialVersionUID = 1L;
  123. boolean[] columnEditables = new boolean[] { true, true, true, false, true };
  124. public boolean isCellEditable(int row, int column) {
  125. return columnEditables[column];
  126. }
  127. });
  128. tblUsers.getColumnModel().getColumn(0).setPreferredWidth(56);
  129. tblUsers.getColumnModel().getColumn(1).setPreferredWidth(118);
  130. tblUsers.getColumnModel().getColumn(2).setPreferredWidth(126);
  131. tblUsers.getColumnModel().getColumn(3).setResizable(false);
  132. tblUsers.getColumnModel().getColumn(3).setPreferredWidth(61);
  133. tblUsers.getColumnModel().getColumn(4).setPreferredWidth(122);
  134. scrollPane_1.setViewportView(tblUsers);
  135. // 更换样式
  136. try {
  137. String style = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
  138. UIManager.setLookAndFeel(style);
  139. SwingUtilities.updateComponentTreeUI(this.frmTcp);
  140. } catch (Exception e) {
  141. e.printStackTrace();
  142. }
  143. }
  144. public static void main(String[] args) {
  145. ServerUI serverUI = ServerUI.GetServerUI();
  146. serverUI.frmTcp.setVisible(true);
  147. }
  148. }

5、ServerSide包里面

(1)Server代码

  1. package ServerSide;
  2. import java.awt.event.ActionEvent;
  3. import java.awt.event.ActionListener;
  4. import java.io.DataInputStream;
  5. import java.io.DataOutputStream;
  6. import java.io.IOException;
  7. import java.net.InetSocketAddress;
  8. import java.net.ServerSocket;
  9. import java.net.Socket;
  10. import java.net.SocketAddress;
  11. import java.util.HashMap;
  12. import ConnectMysql.OperatorMysql;
  13. import ServerGUI.ServerUI;
  14. public class Server {
  15. private static Server serverInstance=null;
  16. public static synchronized Server GetServer()
  17. {
  18. if(serverInstance==null)
  19. {
  20. serverInstance=new Server();
  21. }
  22. return serverInstance;
  23. }
  24. // 对数据库进行操作
  25. private static OperatorMysql operatorMysql = new OperatorMysql();
  26. private String userName;
  27. private String userPassword;
  28. ServerUI serverUI = ServerUI.GetServerUI();
  29. // 服务器套接字
  30. private ServerSocket server;
  31. // 服务器是否运行
  32. private boolean isRunning;
  33. // 用户名不能相同,存放每个用户和客户端套接字的映射。
  34. private HashMap<String, ClientHandler> clientHandlerMap = new HashMap<String, ClientHandler>();
  35. // 注册
  36. public Boolean Register(String userName, String userPassword) {
  37. if (operatorMysql.Search(userName)) {
  38. operatorMysql.Insert(userName, userPassword);
  39. this.userName = userName;
  40. this.userPassword = userPassword;
  41. return true;
  42. }
  43. return false;
  44. }
  45. // 登录
  46. public Boolean LogOn(String userName, String userPassword) {
  47. if (operatorMysql.Search(userName)) {
  48. return false;
  49. }
  50. return true;
  51. }
  52. // 内部类,服务器后台线程
  53. public class ServerThread implements Runnable {
  54. // 启动
  55. private void startServer() {
  56. try {
  57. // 获取serverIp 和 serverPort
  58. String serverIp = serverUI.GetTextServerIP().getText();
  59. int serverPort = Integer.parseInt(serverUI.GetTextPort().getText());
  60. // 创建套接字地址
  61. SocketAddress socketAddress = new InetSocketAddress(serverIp, serverPort);
  62. // 创建ServerSocket,绑定套接字地址
  63. server = new ServerSocket();
  64. server.bind(socketAddress);
  65. // 修改判断服务器是否运行的标识变量
  66. isRunning = true;
  67. // 修改启动和停止按钮状态
  68. serverUI.GetBtnStart().setEnabled(false);
  69. serverUI.GetBtnStop().setEnabled(true);
  70. addMsg("服务器启动成功");
  71. System.out.println("服务器启动成功");
  72. } catch (IOException e) {
  73. addMsg("服务器启动失败,请检查端口是否被占用");
  74. e.printStackTrace();
  75. isRunning = false;
  76. }
  77. }
  78. // 线程主体
  79. @Override
  80. public void run() {
  81. startServer();
  82. CloseServer();
  83. // 当服务器处于运行状态时,循环监听客户端的连接请求
  84. while (isRunning) {
  85. try {
  86. Socket socket = server.accept();
  87. // 创建与客户端交互的线程
  88. Thread thread = new Thread(new ClientHandler(socket));
  89. thread.start();
  90. } catch (IOException e) {
  91. }
  92. }
  93. }
  94. }
  95. public void CloseServer() {
  96. serverUI.GetBtnStop().addActionListener(new ActionListener() {
  97. @Override
  98. public void actionPerformed(ActionEvent e) {
  99. try {
  100. isRunning = false;
  101. server.close();
  102. clientHandlerMap.clear();
  103. // 修改按钮状态
  104. serverUI.GetBtnStart().setEnabled(true);
  105. serverUI.GetBtnStop().setEnabled(false);
  106. addMsg("服务器关闭成功");
  107. } catch (IOException e1) {
  108. e1.printStackTrace();
  109. }
  110. }
  111. });
  112. }
  113. // 添加消息到文本框textAreaRecord
  114. private void addMsg(String msg) {
  115. // 在文本区中添加一条消息,并加上换行
  116. serverUI.GetTextAreaRecord().append(msg + "\n");
  117. // 自动滚动到文本区的最后一行
  118. serverUI.GetTextAreaRecord().setCaretPosition(serverUI.GetTextAreaRecord().getText().length());
  119. }
  120. //更新服务器在线用户表
  121. public void UpdateUserTbl() {
  122. }
  123. //获取IP地址
  124. public Object GetInetAddress() {
  125. return null;
  126. }
  127. //获取端口号
  128. public int GetPort()
  129. {
  130. return 6666;
  131. }
  132. // 内部类,用于和客户端交互
  133. class ClientHandler implements Runnable {
  134. private Socket socket;
  135. private DataInputStream dis;
  136. private DataOutputStream dos;
  137. private boolean isConnected;
  138. private String username;
  139. public ClientHandler(Socket socket) {
  140. this.socket = socket;
  141. try {
  142. this.dis = new DataInputStream(socket.getInputStream());
  143. this.dos = new DataOutputStream(socket.getOutputStream());
  144. isConnected = true;
  145. } catch (IOException e) {
  146. isConnected = false;
  147. e.printStackTrace();
  148. }
  149. }
  150. @Override
  151. public void run() {
  152. while (isRunning && isConnected) {
  153. try {
  154. // 读取客户端发送的报文
  155. String msg = dis.readUTF();
  156. String[] parts = msg.split("#");
  157. switch (parts[0]) {
  158. // 处理登录报文
  159. case "CONNECT":
  160. String connectUsername = parts[1];
  161. // 如果该用户名已登录,则返回失败报文,否则返回成功报文
  162. if (clientHandlerMap.containsKey(connectUsername)) {
  163. dos.writeUTF("FAIL");
  164. } else {
  165. dos.writeUTF("SUCCESS");
  166. // 将此客户端处理线程的信息添加到clientHandlerMap中
  167. clientHandlerMap.put(connectUsername, this);
  168. // 将现有用户的信息发给新用户
  169. StringBuffer msgUserList = new StringBuffer();
  170. msgUserList.append("USERLIST#");
  171. for (String username : clientHandlerMap.keySet()) {
  172. msgUserList.append(username + "#");
  173. }
  174. dos.writeUTF(msgUserList.toString());
  175. // 将新登录的用户信息广播给其他用户
  176. String msgLogin = "CONNECT#" + connectUsername;
  177. BroadcastMsg(connectUsername, msgLogin);
  178. // 存储登录的用户名
  179. this.username = connectUsername;
  180. UpdateUserTbl();// 未实现
  181. }
  182. break;
  183. // 处理退出报文
  184. case "DISCONNECT":
  185. clientHandlerMap.remove(username);
  186. String msgLogout = "DISCONNECT#" + username;
  187. BroadcastMsg(username, msgLogout);
  188. isConnected = false;
  189. dis.close();
  190. dos.close();
  191. socket.close();
  192. UpdateUserTbl();
  193. break;
  194. case "TALKTO_ALL":
  195. String msgTalkToAll = "TALKTO_ALL#" + username + "#" + parts[1];
  196. BroadcastMsg(username, msgTalkToAll);
  197. break;
  198. case "TALKTO":
  199. ClientHandler clientHandler = clientHandlerMap.get(parts[1]);
  200. if (null != clientHandler) {
  201. String msgTalkTo = "TALKTO#" + username + "#" + parts[2];
  202. clientHandler.dos.writeUTF(msgTalkTo);
  203. clientHandler.dos.flush();
  204. }
  205. default:
  206. break;
  207. }
  208. } catch (IOException e) {
  209. isConnected = false;
  210. e.printStackTrace();
  211. }
  212. }
  213. }
  214. // 将某个用户发来的消息广播给其它用户
  215. private void BroadcastMsg(String fromUsername, String msg) throws IOException {
  216. for (String toUserName : clientHandlerMap.keySet()) {
  217. if (fromUsername.equals(toUserName) == false) {
  218. DataOutputStream dos = clientHandlerMap.get(toUserName).dos;
  219. dos.writeUTF(msg);
  220. dos.flush();
  221. }
  222. }
  223. }
  224. }
  225. }

6、Utils包里面

(1)Utils代码

  1. package Utils;
  2. import java.io.DataInputStream;
  3. import java.io.DataOutputStream;
  4. import java.io.IOException;
  5. import java.net.Socket;
  6. import javax.swing.JTextArea;
  7. public class Utils {
  8. // 通过套接字S发送字符串
  9. public static void sendMsg(Socket s, String msg) {
  10. try {
  11. // 字符流
  12. DataOutputStream dos = new DataOutputStream(s.getOutputStream());
  13. dos.writeUTF(msg);
  14. dos.flush();
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. }
  18. }
  19. // 在套接字S上读取字符串,如果TCP连接关闭,返回null
  20. public static String recvMsg(Socket s) throws IOException {
  21. String msg = null;
  22. DataInputStream dis = (DataInputStream) new DataInputStream(s.getInputStream());
  23. msg = ((DataInputStream) dis).readUTF();
  24. return msg;
  25. }
  26. // 添加消息到文本记录框JTextArea,并且滚动显示到最后一行
  27. public static void addMsgRec(JTextArea textArea, String msg) {
  28. textArea.append(msg + "\n");
  29. textArea.setCaretPosition(textArea.getText().length());
  30. }
  31. }

最后添加一个Mysql的库文件就可以连接数据库了。

测试如下:

首先,打开mysql数据库,然后启动服务器启动成功,如下图。

然后启动登录界面,如下图:

点击注册按钮,进入注册界面,如下图:

进行注册,如果注册成功就会进行注册成功提示,如下图:

如果用户名已经注册就会进行注册失败提示,如下图:

点击返回按钮进入登录界面进行登录,如果用户名不存在会提示登录失败,如下图:

如果不输入任何东西点击登录也会提示用户进行输入,如下图:

登录成功以后就进入客户端主界面,如下图:

界面上有在线用户和上线提示。

然后通过重复前面的步骤在开两个客户端,此时界面,如下图:

然后就可以进行聊天了,首先默认的是群聊,如下图:

群聊正常的实现了。

私聊主要就是选择私聊按钮,然后选择想要私聊的用户,如果不选择私聊用户,就会进行提醒,如下图:‘

选择在线用户后就可以进行私聊了,如下图:

正常实现了,不过这里还有一个问题就是如果选择自己的话也能进行私聊,这就不对了,如下图:

因为时间原因,服务器端没有全部进行完善,还有一部分功能没有实现,如下图:

源代码下载:下载链接

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/178623
推荐阅读
相关标签
  

闽ICP备14008679号