系統基本功能描述html
客戶端能夠實現註冊,即時聊天,相互之間收發文件,發送截圖,查看歷史聊天記錄java
等功能。收發消息時,能夠實現離線接收。數據庫
服務器端應當創建一個數組
ServerSocket服務器
,app
而且不斷進行偵聽是否有客戶端鏈接或者斷開eclipse
鏈接socket
(ide
包括判斷沒有響應的鏈接超時this
)
。服務器端應當是一個信息發送中心,全部客戶端的
信息都傳到服務器端,由服務器端根據要求分發信息。
在後臺管理系統,能夠到對用戶進行增刪改查,查看在線用戶,和踢用戶下線
本系統要實現的功能以下:
1)
註冊
服務器收到用戶的註冊請求,便開始接受客戶傳遞的信息,諸如客戶的呢稱,性別,
籍貫,我的資料等,接受完畢後,便經過
JDBC
與後臺數據庫鏈接,而後向數據庫添加記
錄,若是成功,便向客戶返回其號碼。客戶收到服務器返回的信息後,便打開窗口登錄。
2)
登錄
在客戶端,
用戶輸入其號碼和密碼,
而後創建與服務器的鏈接,
告訴服務器我要登陸,
服務器收到後,
開始經過
JDBC
讀取數據庫,
而後與用戶輸入的信息進行比對,
若是成功,
便打開主程序窗口。而後客戶向服務器請求讀取好友名單,服務器收到該請求,從數據庫
中取出好友列表,而後向客戶端發送這些信息,客戶收到後就在主窗口顯示好友。
3)
聊天
客戶端首先發送消息到服務器端,服務器端根據發送人信息和接收者信息來轉發。例
如服務器接收到一個
A
發給
B
的消息,先判斷
B
是否已經在線,若是在線就將信息發送
過去。
若是
B
不在線則把信息儲存在服務器,
等
B
上線了在發送給他。
B
接收到
A
發來的
信息,若是是未創建對話窗口,則自動打開顯示。
4)
發送截圖
客戶端
A
點擊截圖按鈕,將屏幕鎖定,截取圖片,將圖片儲存在
byte[]
數組中發送到
服務器端。服務器端根據發送人信息和接收者信息來轉發。
B
接收到
A
發來的截圖信息,
會根據
byte[]
構造圖片,將圖片顯示出來。一樣,若是是未創建對話窗口,則自動打開顯
示。
5)
發送文件
客戶端
A
點擊發送文件按鍵,從本地選擇文件,將文件在
byte[]
數組中分批次發送到
服務器端。服務器端根據發送人信息和接收者信息來轉發。
B
接收到
A
發來的文件信息,
會根據文件發送的狀態和
byte[]
構造文件。
6)
日誌
客戶端發送和接收到的信息都會儲存在文本文檔中。默認儲存在
C
盤下面,會以用戶
的登陸帳號爲名。
7)
對用戶的操做
管理員經過
B/S
的系統對用戶進行增長,
修改,
刪除,
查找等操做,
對系統進行維護。
8)
在線用戶的操做
管理員經過
B/S
的系統對在線用戶操做,能夠踢用戶下線。
界面是用swing寫的,還不懶,簡約大方。有圖有真相:
正如上圖所示,這個程序分爲 服務器端和客戶端,說白了就是 兩個main class,用eclipse直接運行之。。。。。
聊天室的設計思想是 :在局域網下, 利用socket進行鏈接通訊,當服務器端啓動的時候,利用Thread線程不停的等待客戶端的連接;當有客戶端開啓連
接的時候,服務器端經過IO流反饋「上線用戶」信息給客戶端,客戶端也使用線程不停的接收服務器的信息,從而實現多人在線聊天功能。
程序中有三個類,分別 Server.Java(服務器端)、Client(客戶端)、User.java(javabean)。代碼以下:
Server.java(服務器端):
[html] view plain copy
- import java.awt.BorderLayout;
- import java.awt.Color;
- import java.awt.GridLayout;
- import java.awt.Toolkit;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.WindowAdapter;
- import java.awt.event.WindowEvent;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.net.BindException;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.util.ArrayList;
- import java.util.StringTokenizer;
-
- import javax.swing.DefaultListModel;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JLabel;
- import javax.swing.JList;
- import javax.swing.JOptionPane;
- import javax.swing.JPanel;
- import javax.swing.JScrollPane;
- import javax.swing.JSplitPane;
- import javax.swing.JTextArea;
- import javax.swing.JTextField;
- import javax.swing.border.TitledBorder;
-
- public class Server {
-
- private JFrame frame;
- private JTextArea contentArea;
- private JTextField txt_message;
- private JTextField txt_max;
- private JTextField txt_port;
- private JButton btn_start;
- private JButton btn_stop;
- private JButton btn_send;
- private JPanel northPanel;
- private JPanel southPanel;
- private JScrollPane rightPanel;
- private JScrollPane leftPanel;
- private JSplitPane centerSplit;
- private JList userList;
- private DefaultListModel listModel;
-
- private ServerSocket serverSocket;
- private ServerThread serverThread;
- private ArrayList<ClientThread> clients;
-
- private boolean isStart = false;
-
- // 主方法,程序執行入口
- public static void main(String[] args) {
- new Server();
- }
-
- // 執行消息發送
- public void send() {
- if (!isStart) {
- JOptionPane.showMessageDialog(frame, "服務器還未啓動,不能發送消息!", "錯誤",
- JOptionPane.ERROR_MESSAGE);
- return;
- }
- if (clients.size() == 0) {
- JOptionPane.showMessageDialog(frame, "沒有用戶在線,不能發送消息!", "錯誤",
- JOptionPane.ERROR_MESSAGE);
- return;
- }
- String message = txt_message.getText().trim();
- if (message == null || message.equals("")) {
- JOptionPane.showMessageDialog(frame, "消息不能爲空!", "錯誤",
- JOptionPane.ERROR_MESSAGE);
- return;
- }
- sendServerMessage(message);// 羣發服務器消息
- contentArea.append("服務器說:" + txt_message.getText() + "\r\n");
- txt_message.setText(null);
- }
-
- // 構造放法
- public Server() {
- frame = new JFrame("服務器");
- // 更改JFrame的圖標:
- //frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Client.class.getResource("qq.png")));
- frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Server.class.getResource("qq.png")));
- contentArea = new JTextArea();
- contentArea.setEditable(false);
- contentArea.setForeground(Color.blue);
- txt_message = new JTextField();
- txt_max = new JTextField("30");
- txt_port = new JTextField("6666");
- btn_start = new JButton("啓動");
- btn_stop = new JButton("中止");
- btn_send = new JButton("發送");
- btn_stop.setEnabled(false);
- listModel = new DefaultListModel();
- userList = new JList(listModel);
-
- southPanel = new JPanel(new BorderLayout());
- southPanel.setBorder(new TitledBorder("寫消息"));
- southPanel.add(txt_message, "Center");
- southPanel.add(btn_send, "East");
- leftPanel = new JScrollPane(userList);
- leftPanel.setBorder(new TitledBorder("在線用戶"));
-
- rightPanel = new JScrollPane(contentArea);
- rightPanel.setBorder(new TitledBorder("消息顯示區"));
-
- centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel,
- rightPanel);
- centerSplit.setDividerLocation(100);
- northPanel = new JPanel();
- northPanel.setLayout(new GridLayout(1, 6));
- northPanel.add(new JLabel("人數上限"));
- northPanel.add(txt_max);
- northPanel.add(new JLabel("端口"));
- northPanel.add(txt_port);
- northPanel.add(btn_start);
- northPanel.add(btn_stop);
- northPanel.setBorder(new TitledBorder("配置信息"));
-
- frame.setLayout(new BorderLayout());
- frame.add(northPanel, "North");
- frame.add(centerSplit, "Center");
- frame.add(southPanel, "South");
- frame.setSize(600, 400);
- //frame.setSize(Toolkit.getDefaultToolkit().getScreenSize());//設置全屏
- int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
- int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
- frame.setLocation((screen_width - frame.getWidth()) / 2,
- (screen_height - frame.getHeight()) / 2);
- frame.setVisible(true);
-
- // 關閉窗口時事件
- frame.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- if (isStart) {
- closeServer();// 關閉服務器
- }
- System.exit(0);// 退出程序
- }
- });
-
- // 文本框按回車鍵時事件
- txt_message.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- send();
- }
- });
-
- // 單擊發送按鈕時事件
- btn_send.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent arg0) {
- send();
- }
- });
-
- // 單擊啓動服務器按鈕時事件
- btn_start.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (isStart) {
- JOptionPane.showMessageDialog(frame, "服務器已處於啓動狀態,不要重複啓動!",
- "錯誤", JOptionPane.ERROR_MESSAGE);
- return;
- }
- int max;
- int port;
- try {
- try {
- max = Integer.parseInt(txt_max.getText());
- } catch (Exception e1) {
- throw new Exception("人數上限爲正整數!");
- }
- if (max <= 0) {
- throw new Exception("人數上限爲正整數!");
- }
- try {
- port = Integer.parseInt(txt_port.getText());
- } catch (Exception e1) {
- throw new Exception("端口號爲正整數!");
- }
- if (port <= 0) {
- throw new Exception("端口號 爲正整數!");
- }
- serverStart(max, port);
- contentArea.append("服務器已成功啓動!人數上限:" + max + ",端口:" + port
- + "\r\n");
- JOptionPane.showMessageDialog(frame, "服務器成功啓動!");
- btn_start.setEnabled(false);
- txt_max.setEnabled(false);
- txt_port.setEnabled(false);
- btn_stop.setEnabled(true);
- } catch (Exception exc) {
- JOptionPane.showMessageDialog(frame, exc.getMessage(),
- "錯誤", JOptionPane.ERROR_MESSAGE);
- }
- }
- });
-
- // 單擊中止服務器按鈕時事件
- btn_stop.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (!isStart) {
- JOptionPane.showMessageDialog(frame, "服務器還未啓動,無需中止!", "錯誤",
- JOptionPane.ERROR_MESSAGE);
- return;
- }
- try {
- closeServer();
- btn_start.setEnabled(true);
- txt_max.setEnabled(true);
- txt_port.setEnabled(true);
- btn_stop.setEnabled(false);
- contentArea.append("服務器成功中止!\r\n");
- JOptionPane.showMessageDialog(frame, "服務器成功中止!");
- } catch (Exception exc) {
- JOptionPane.showMessageDialog(frame, "中止服務器發生異常!", "錯誤",
- JOptionPane.ERROR_MESSAGE);
- }
- }
- });
- }
-
- // 啓動服務器
- public void serverStart(int max, int port) throws java.net.BindException {
- try {
- clients = new ArrayList<ClientThread>();
- serverSocket = new ServerSocket(port);
- serverThread = new ServerThread(serverSocket, max);
- serverThread.start();
- isStart = true;
- } catch (BindException e) {
- isStart = false;
- throw new BindException("端口號已被佔用,請換一個!");
- } catch (Exception e1) {
- e1.printStackTrace();
- isStart = false;
- throw new BindException("啓動服務器異常!");
- }
- }
-
- // 關閉服務器
- @SuppressWarnings("deprecation")
- public void closeServer() {
- try {
- if (serverThread != null)
- serverThread.stop();// 中止服務器線程
-
- for (int i = clients.size() - 1; i >= 0; i--) {
- // 給全部在線用戶發送關閉命令
- clients.get(i).getWriter().println("CLOSE");
- clients.get(i).getWriter().flush();
- // 釋放資源
- clients.get(i).stop();// 中止此條爲客戶端服務的線程
- clients.get(i).reader.close();
- clients.get(i).writer.close();
- clients.get(i).socket.close();
- clients.remove(i);
- }
- if (serverSocket != null) {
- serverSocket.close();// 關閉服務器端鏈接
- }
- listModel.removeAllElements();// 清空用戶列表
- isStart = false;
- } catch (IOException e) {
- e.printStackTrace();
- isStart = true;
- }
- }
-
- // 羣發服務器消息
- public void sendServerMessage(String message) {
- for (int i = clients.size() - 1; i >= 0; i--) {
- clients.get(i).getWriter().println("服務器:" + message + "(多人發送)");
- clients.get(i).getWriter().flush();
- }
- }
-
- // 服務器線程
- class ServerThread extends Thread {
- private ServerSocket serverSocket;
- private int max;// 人數上限
-
- // 服務器線程的構造方法
- public ServerThread(ServerSocket serverSocket, int max) {
- this.serverSocket = serverSocket;
- this.max = max;
- }
-
- public void run() {
- while (true) {// 不停的等待客戶端的連接
- try {
- Socket socket = serverSocket.accept();
- if (clients.size() == max) {// 若是已達人數上限
- BufferedReader r = new BufferedReader(
- new InputStreamReader(socket.getInputStream()));
- PrintWriter w = new PrintWriter(socket
- .getOutputStream());
- // 接收客戶端的基本用戶信息
- String inf = r.readLine();
- StringTokenizer st = new StringTokenizer(inf, "@");
- User user = new User(st.nextToken(), st.nextToken());
- // 反饋鏈接成功信息
- w.println("MAX@服務器:對不起," + user.getName()
- + user.getIp() + ",服務器在線人數已達上限,請稍後嘗試鏈接!");
- w.flush();
- // 釋放資源
- r.close();
- w.close();
- socket.close();
- continue;
- }
- ClientThread client = new ClientThread(socket);
- client.start();// 開啓對此客戶端服務的線程
- clients.add(client);
- listModel.addElement(client.getUser().getName());// 更新在線列表
- contentArea.append(client.getUser().getName()
- + client.getUser().getIp() + "上線!\r\n");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- // 爲一個客戶端服務的線程
- class ClientThread extends Thread {
- private Socket socket;
- private BufferedReader reader;
- private PrintWriter writer;
- private User user;
-
- public BufferedReader getReader() {
- return reader;
- }
-
- public PrintWriter getWriter() {
- return writer;
- }
-
- public User getUser() {
- return user;
- }
-
- // 客戶端線程的構造方法
- public ClientThread(Socket socket) {
- try {
- this.socket = socket;
- reader = new BufferedReader(new InputStreamReader(socket
- .getInputStream()));
- writer = new PrintWriter(socket.getOutputStream());
- // 接收客戶端的基本用戶信息
- String inf = reader.readLine();
- StringTokenizer st = new StringTokenizer(inf, "@");
- user = new User(st.nextToken(), st.nextToken());
- // 反饋鏈接成功信息
- writer.println(user.getName() + user.getIp() + "與服務器鏈接成功!");
- writer.flush();
- // 反饋當前在線用戶信息
- if (clients.size() > 0) {
- String temp = "";
- for (int i = clients.size() - 1; i >= 0; i--) {
- temp += (clients.get(i).getUser().getName() + "/" + clients
- .get(i).getUser().getIp())
- + "@";
- }
- writer.println("USERLIST@" + clients.size() + "@" + temp);
- writer.flush();
- }
- // 向全部在線用戶發送該用戶上線命令
- for (int i = clients.size() - 1; i >= 0; i--) {
- clients.get(i).getWriter().println(
- "ADD@" + user.getName() + user.getIp());
- clients.get(i).getWriter().flush();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- @SuppressWarnings("deprecation")
- public void run() {// 不斷接收客戶端的消息,進行處理。
- String message = null;
- while (true) {
- try {
- message = reader.readLine();// 接收客戶端消息
- if (message.equals("CLOSE"))// 下線命令
- {
- contentArea.append(this.getUser().getName()
- + this.getUser().getIp() + "下線!\r\n");
- // 斷開鏈接釋放資源
- reader.close();
- writer.close();
- socket.close();
-
- // 向全部在線用戶發送該用戶的下線命令
- for (int i = clients.size() - 1; i >= 0; i--) {
- clients.get(i).getWriter().println(
- "DELETE@" + user.getName());
- clients.get(i).getWriter().flush();
- }
-
- listModel.removeElement(user.getName());// 更新在線列表
-
- // 刪除此條客戶端服務線程
- for (int i = clients.size() - 1; i >= 0; i--) {
- if (clients.get(i).getUser() == user) {
- ClientThread temp = clients.get(i);
- clients.remove(i);// 刪除此用戶的服務線程
- temp.stop();// 中止這條服務線程
- return;
- }
- }
- } else {
- dispatcherMessage(message);// 轉發消息
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- // 轉發消息
- public void dispatcherMessage(String message) {
- StringTokenizer stringTokenizer = new StringTokenizer(message, "@");
- String source = stringTokenizer.nextToken();
- String owner = stringTokenizer.nextToken();
- String content = stringTokenizer.nextToken();
- message = source + "說:" + content;
- contentArea.append(message + "\r\n");
- if (owner.equals("ALL")) {// 羣發
- for (int i = clients.size() - 1; i >= 0; i--) {
- clients.get(i).getWriter().println(message + "(多人發送)");
- clients.get(i).getWriter().flush();
- }
- }
- }
- }
- }
Client(客戶端):
[html] view plain copy
- import java.awt.BorderLayout;
- import java.awt.Color;
- import java.awt.GridLayout;
- import java.awt.Toolkit;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.WindowAdapter;
- import java.awt.event.WindowEvent;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.net.Socket;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.StringTokenizer;
-
- import javax.swing.DefaultListModel;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JLabel;
- import javax.swing.JList;
- import javax.swing.JOptionPane;
- import javax.swing.JPanel;
- import javax.swing.JScrollPane;
- import javax.swing.JSplitPane;
- import javax.swing.JTextArea;
- import javax.swing.JTextField;
- import javax.swing.border.TitledBorder;
-
- public class Client{
-
- private JFrame frame;
- private JList userList;
- private JTextArea textArea;
- private JTextField textField;
- private JTextField txt_port;
- private JTextField txt_hostIp;
- private JTextField txt_name;
- private JButton btn_start;
- private JButton btn_stop;
- private JButton btn_send;
- private JPanel northPanel;
- private JPanel southPanel;
- private JScrollPane rightScroll;
- private JScrollPane leftScroll;
- private JSplitPane centerSplit;
-
- private DefaultListModel listModel;
- private boolean isConnected = false;
-
- private Socket socket;
- private PrintWriter writer;
- private BufferedReader reader;
- private MessageThread messageThread;// 負責接收消息的線程
- private Map<String, User> onLineUsers = new HashMap<String, User>();// 全部在線用戶
-
- // 主方法,程序入口
- public static void main(String[] args) {
- new Client();
- }
-
- // 執行發送
- public void send() {
- if (!isConnected) {
- JOptionPane.showMessageDialog(frame, "尚未鏈接服務器,沒法發送消息!", "錯誤",
- JOptionPane.ERROR_MESSAGE);
- return;
- }
- String message = textField.getText().trim();
- if (message == null || message.equals("")) {
- JOptionPane.showMessageDialog(frame, "消息不能爲空!", "錯誤",
- JOptionPane.ERROR_MESSAGE);
- return;
- }
- sendMessage(frame.getTitle() + "@" + "ALL" + "@" + message);
- textField.setText(null);
- }
-
- // 構造方法
- public Client() {
- textArea = new JTextArea();
- textArea.setEditable(false);
- textArea.setForeground(Color.blue);
- textField = new JTextField();
- txt_port = new JTextField("6666");
- txt_hostIp = new JTextField("127.0.0.1");
- txt_name = new JTextField("xiaoqiang");
- btn_start = new JButton("鏈接");
- btn_stop = new JButton("斷開");
- btn_send = new JButton("發送");
- listModel = new DefaultListModel();
- userList = new JList(listModel);
-
- northPanel = new JPanel();
- northPanel.setLayout(new GridLayout(1, 7));
- northPanel.add(new JLabel("端口"));
- northPanel.add(txt_port);
- northPanel.add(new JLabel("服務器IP"));
- northPanel.add(txt_hostIp);
- northPanel.add(new JLabel("姓名"));
- northPanel.add(txt_name);
- northPanel.add(btn_start);
- northPanel.add(btn_stop);
- northPanel.setBorder(new TitledBorder("鏈接信息"));
-
- rightScroll = new JScrollPane(textArea);
- rightScroll.setBorder(new TitledBorder("消息顯示區"));
- leftScroll = new JScrollPane(userList);
- leftScroll.setBorder(new TitledBorder("在線用戶"));
- southPanel = new JPanel(new BorderLayout());
- southPanel.add(textField, "Center");
- southPanel.add(btn_send, "East");
- southPanel.setBorder(new TitledBorder("寫消息"));
-
- centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftScroll,
- rightScroll);
- centerSplit.setDividerLocation(100);
-
- frame = new JFrame("客戶機");
- // 更改JFrame的圖標:
- frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Client.class.getResource("qq.png")));
- frame.setLayout(new BorderLayout());
- frame.add(northPanel, "North");
- frame.add(centerSplit, "Center");
- frame.add(southPanel, "South");
- frame.setSize(600, 400);
- int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
- int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
- frame.setLocation((screen_width - frame.getWidth()) / 2,
- (screen_height - frame.getHeight()) / 2);
- frame.setVisible(true);
-
- // 寫消息的文本框中按回車鍵時事件
- textField.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent arg0) {
- send();
- }
- });
-
- // 單擊發送按鈕時事件
- btn_send.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- send();
- }
- });
-
- // 單擊鏈接按鈕時事件
- btn_start.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- int port;
- if (isConnected) {
- JOptionPane.showMessageDialog(frame, "已處於鏈接上狀態,不要重複鏈接!",
- "錯誤", JOptionPane.ERROR_MESSAGE);
- return;
- }
- try {
- try {
- port = Integer.parseInt(txt_port.getText().trim());
- } catch (NumberFormatException e2) {
- throw new Exception("端口號不符合要求!端口爲整數!");
- }
- String hostIp = txt_hostIp.getText().trim();
- String name = txt_name.getText().trim();
- if (name.equals("") || hostIp.equals("")) {
- throw new Exception("姓名、服務器IP不能爲空!");
- }
- boolean flag = connectServer(port, hostIp, name);
- if (flag == false) {
- throw new Exception("與服務器鏈接失敗!");
- }
- frame.setTitle(name);
- JOptionPane.showMessageDialog(frame, "成功鏈接!");
- } catch (Exception exc) {
- JOptionPane.showMessageDialog(frame, exc.getMessage(),
- "錯誤", JOptionPane.ERROR_MESSAGE);
- }
- }
- });
-
- // 單擊斷開按鈕時事件
- btn_stop.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (!isConnected) {
- JOptionPane.showMessageDialog(frame, "已處於斷開狀態,不要重複斷開!",
- "錯誤", JOptionPane.ERROR_MESSAGE);
- return;
- }
- try {
- boolean flag = closeConnection();// 斷開鏈接
- if (flag == false) {
- throw new Exception("斷開鏈接發生異常!");
- }
- JOptionPane.showMessageDialog(frame, "成功斷開!");
- } catch (Exception exc) {
- JOptionPane.showMessageDialog(frame, exc.getMessage(),
- "錯誤", JOptionPane.ERROR_MESSAGE);
- }
- }
- });
-
- // 關閉窗口時事件
- frame.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- if (isConnected) {
- closeConnection();// 關閉鏈接
- }
- System.exit(0);// 退出程序
- }
- });
- }
-
- /**
- * 鏈接服務器
- *
- * @param port
- * @param hostIp
- * @param name
- */
- public boolean connectServer(int port, String hostIp, String name) {
- // 鏈接服務器
- try {
- socket = new Socket(hostIp, port);// 根據端口號和服務器ip創建鏈接
- writer = new PrintWriter(socket.getOutputStream());
- reader = new BufferedReader(new InputStreamReader(socket
- .getInputStream()));
- // 發送客戶端用戶基本信息(用戶名和ip地址)
- sendMessage(name + "@" + socket.getLocalAddress().toString());
- // 開啓接收消息的線程
- messageThread = new MessageThread(reader, textArea);
- messageThread.start();
- isConnected = true;// 已經鏈接上了
- return true;
- } catch (Exception e) {
- textArea.append("與端口號爲:" + port + " IP地址爲:" + hostIp
- + " 的服務器鏈接失敗!" + "\r\n");
- isConnected = false;// 未鏈接上
- return false;
- }
- }
-
- /**
- * 發送消息
- *
- * @param message
- */
- public void sendMessage(String message) {
- writer.println(message);
- writer.flush();
- }
-
- /**
- * 客戶端主動關閉鏈接
- */
- @SuppressWarnings("deprecation")
- public synchronized boolean closeConnection() {
- try {
- sendMessage("CLOSE");// 發送斷開鏈接命令給服務器
- messageThread.stop();// 中止接受消息線程
- // 釋放資源
- if (reader != null) {
- reader.close();
- }
- if (writer != null) {
- writer.close();
- }
- if (socket != null) {
- socket.close();
- }
- isConnected = false;
- return true;
- } catch (IOException e1) {
- e1.printStackTrace();
- isConnected = true;
- return false;
- }
- }
-
- // 不斷接收消息的線程
- class MessageThread extends Thread {
- private BufferedReader reader;
- private JTextArea textArea;
-
- // 接收消息線程的構造方法
- public MessageThread(BufferedReader reader, JTextArea textArea) {
- this.reader = reader;
- this.textArea = textArea;
- }
-
- // 被動的關閉鏈接
- public synchronized void closeCon() throws Exception {
- // 清空用戶列表
- listModel.removeAllElements();
- // 被動的關閉鏈接釋放資源
- if (reader != null) {
- reader.close();
- }
- if (writer != null) {
- writer.close();
- }
- if (socket != null) {
- socket.close();
- }
- isConnected = false;// 修改狀態爲斷開
- }
-
- public void run() {
- String message = "";
- while (true) {
- try {
- message = reader.readLine();
- StringTokenizer stringTokenizer = new StringTokenizer(
- message, "/@");
- String command = stringTokenizer.nextToken();// 命令
- if (command.equals("CLOSE"))// 服務器已關閉命令
- {
- textArea.append("服務器已關閉!\r\n");
- closeCon();// 被動的關閉鏈接
- return;// 結束線程
- } else if (command.equals("ADD")) {// 有用戶上線更新在線列表
- String username = "";
- String userIp = "";
- if ((username = stringTokenizer.nextToken()) != null
- && (userIp = stringTokenizer.nextToken()) != null) {
- User user = new User(username, userIp);
- onLineUsers.put(username, user);
- listModel.addElement(username);
- }
- } else if (command.equals("DELETE")) {// 有用戶下線更新在線列表
- String username = stringTokenizer.nextToken();
- User user = (User) onLineUsers.get(username);
- onLineUsers.remove(user);
- listModel.removeElement(username);
- } else if (command.equals("USERLIST")) {// 加載在線用戶列表
- int size = Integer
- .parseInt(stringTokenizer.nextToken());
- String username = null;
- String userIp = null;
- for (int i = 0; i < size; i++) {
- username = stringTokenizer.nextToken();
- userIp = stringTokenizer.nextToken();
- User user = new User(username, userIp);
- onLineUsers.put(username, user);
- listModel.addElement(username);
- }
- } else if (command.equals("MAX")) {// 人數已達上限
- textArea.append(stringTokenizer.nextToken()
- + stringTokenizer.nextToken() + "\r\n");
- closeCon();// 被動的關閉鏈接
- JOptionPane.showMessageDialog(frame, "服務器緩衝區已滿!", "錯誤",
- JOptionPane.ERROR_MESSAGE);
- return;// 結束線程
- } else {// 普通消息
- textArea.append(message + "\r\n");
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
User.java
[html] view plain copy
- //用戶信息類
- public class User{
- private String name;
- private String ip;
-
- public User(String name, String ip) {
- this.name = name;
- this.ip = ip;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getIp() {
- return ip;
- }
-
- public void setIp(String ip) {
- this.ip = ip;
- }
- }
注: 在eclipse下運行無需另外添加jar文件,其中服務器端和客戶端均須要一張圖片作icon,你們能夠隨便找張圖片補上。 接把圖片放在所建的包下,和三個類文件並列放在一塊兒就行
Java Socket 多人聊天室 swing 局域網