基于java編寫局域網(wǎng)多人聊天室
由于需要制作網(wǎng)絡(luò)計(jì)算機(jī)網(wǎng)絡(luò)課程設(shè)計(jì),并且不想搞網(wǎng)絡(luò)布線或者局域網(wǎng)路由器配置等等這種完全搞不懂的東西,最后決定使用socket基于java編寫一個(gè)局域網(wǎng)聊天室:
關(guān)于socket以及網(wǎng)絡(luò)編程的相關(guān)知識(shí)詳見我另一篇文章:Java基于socket編程
程序基于C/S結(jié)構(gòu),即客戶端服務(wù)器模式。
服務(wù)器:
默認(rèn)ip為本機(jī)ip
需要雙方確定一個(gè)端口號(hào)
可設(shè)置最大連接人數(shù)
可啟動(dòng)與關(guān)閉
界面顯示在線用戶人以及姓名(本機(jī)不在此顯示)
客戶端:
需要手動(dòng)設(shè)置服務(wù)器ip地址(局域網(wǎng))
手動(dòng)設(shè)置端口號(hào)
輸入姓名
可連接可斷開
程序運(yùn)行界面如下:
服務(wù)器:

客戶端:

具體代碼我會(huì)在最后上傳。
軟件有很多不足,其中比如:
沒有與數(shù)據(jù)庫(kù)有任何交集
優(yōu)化:可將所有用戶存放在數(shù)據(jù)庫(kù)中,以及將聊天記錄也放入數(shù)據(jù)庫(kù)中
沒有實(shí)現(xiàn)一對(duì)一聊天
優(yōu)化:需重新定義一對(duì)一聊天的方法
還有許多不足的地方,日后有興趣再回來(lái)慢慢研究
下面為該程序三個(gè)代碼:
User.java
public class User{
/**
* 用戶信息類
* 用于記錄用戶個(gè)人信息:姓名以及IP
*/
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;
}
}
Server_more.java
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_more {
private JFrame frame;
private JTextArea contentArea; //文本域
private JTextField txt_message; //用于顯示文本信息
private JTextField txt_max; //設(shè)置最大連接人數(shù)
private JTextField txt_port; //設(shè)置端口號(hào)
private JButton btn_start; //開始按鈕
private JButton btn_stop; //斷開按鈕
private JButton btn_send; //發(fā)送按鈕
private JPanel northPanel; //北方面板
private JPanel southPanel; //南方面板
private JScrollPane rightPanel; //左邊滾動(dòng)條
private JScrollPane leftPanel; //右邊滾動(dòng)條
private JSplitPane centerSplit; //分割線
private JList userList; //列表組件
private DefaultListModel listModel;
private ServerSocket serverSocket;
private ServerThread serverThread;
private ArrayList<ClientThread> clients;
private boolean isStart = false;
// 主方法,程序執(zhí)行入口
public static void main(String[] args) {
new Server_more();
}
// 執(zhí)行消息發(fā)送
public void send() {
if (!isStart) {
JOptionPane.showMessageDialog(frame, "服務(wù)器還未啟動(dòng),不能發(fā)送消息!", "錯(cuò)誤",
JOptionPane.ERROR_MESSAGE);
return;
}
if (clients.size() == 0) {
JOptionPane.showMessageDialog(frame, "沒有用戶在線,不能發(fā)送消息!", "錯(cuò)誤",
JOptionPane.ERROR_MESSAGE);
return;
}
String message = txt_message.getText().trim();
if (message == null || message.equals("")) {
JOptionPane.showMessageDialog(frame, "消息不能為空!", "錯(cuò)誤",
JOptionPane.ERROR_MESSAGE);
return;
}
sendServerMessage(message);// 群發(fā)服務(wù)器消息
contentArea.append("服務(wù)器:" + txt_message.getText() + "\r\n");
txt_message.setText(null);
}
// 構(gòu)造放法
public Server_more() {
frame = new JFrame("服務(wù)器");
// 更改JFrame的圖標(biāo):
//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("啟動(dòng)");
btn_stop = new JButton("停止");
btn_send = new JButton("發(fā)送");
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("消息顯示區(qū)"));
centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel,
rightPanel);
centerSplit.setDividerLocation(100);
northPanel = new JPanel();
northPanel.setLayout(new GridLayout(1, 6));
northPanel.add(new JLabel("人數(shù)上限"));
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());//設(shè)置全屏
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);
// 關(guān)閉窗口時(shí)事件
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (isStart) {
closeServer();// 關(guān)閉服務(wù)器
}
System.exit(0);// 退出程序
}
});
// 文本框按回車鍵時(shí)事件
txt_message.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
send();
}
});
// 單擊發(fā)送按鈕時(shí)事件
btn_send.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
send();
}
});
// 單擊啟動(dòng)服務(wù)器按鈕時(shí)事件
btn_start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (isStart) {
JOptionPane.showMessageDialog(frame, "服務(wù)器已處于啟動(dòng)狀態(tài),不要重復(fù)啟動(dòng)!",
"錯(cuò)誤", JOptionPane.ERROR_MESSAGE);
return;
}
int max;
int port;
try {
try {
max = Integer.parseInt(txt_max.getText());
} catch (Exception e1) {
throw new Exception("人數(shù)上限為正整數(shù)!");
}
if (max <= 0) {
throw new Exception("人數(shù)上限為正整數(shù)!");
}
try {
port = Integer.parseInt(txt_port.getText());
} catch (Exception e1) {
throw new Exception("端口號(hào)為正整數(shù)!");
}
if (port <= 0) {
throw new Exception("端口號(hào) 為正整數(shù)!");
}
serverStart(max, port);
contentArea.append("服務(wù)器已成功啟動(dòng)!人數(shù)上限:" + max + ",端口:" + port
+ "\r\n");
JOptionPane.showMessageDialog(frame, "服務(wù)器成功啟動(dòng)!");
btn_start.setEnabled(false);
txt_max.setEnabled(false);
txt_port.setEnabled(false);
btn_stop.setEnabled(true);
} catch (Exception exc) {
JOptionPane.showMessageDialog(frame, exc.getMessage(),
"錯(cuò)誤", JOptionPane.ERROR_MESSAGE);
}
}
});
// 單擊停止服務(wù)器按鈕時(shí)事件
btn_stop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!isStart) {
JOptionPane.showMessageDialog(frame, "服務(wù)器還未啟動(dòng),無(wú)需停止!", "錯(cuò)誤",
JOptionPane.ERROR_MESSAGE);
return;
}
try {
closeServer();
btn_start.setEnabled(true);
txt_max.setEnabled(true);
txt_port.setEnabled(true);
btn_stop.setEnabled(false);
contentArea.append("服務(wù)器成功停止!\r\n");
JOptionPane.showMessageDialog(frame, "服務(wù)器成功停止!");
} catch (Exception exc) {
JOptionPane.showMessageDialog(frame, "停止服務(wù)器發(fā)生異常!", "錯(cuò)誤",
JOptionPane.ERROR_MESSAGE);
}
}
});
}
// 啟動(dòng)服務(wù)器
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("端口號(hào)已被占用,請(qǐng)換一個(gè)!");
} catch (Exception e1) {
e1.printStackTrace();
isStart = false;
throw new BindException("啟動(dòng)服務(wù)器異常!");
}
}
// 關(guān)閉服務(wù)器
@SuppressWarnings("deprecation")
public void closeServer() {
try {
if (serverThread != null)
serverThread.stop();// 停止服務(wù)器線程
for (int i = clients.size() - 1; i >= 0; i--) {
// 給所有在線用戶發(fā)送關(guān)閉命令
clients.get(i).getWriter().println("CLOSE");
clients.get(i).getWriter().flush();
// 釋放資源
clients.get(i).stop();// 停止此條為客戶端服務(wù)的線程
clients.get(i).reader.close();
clients.get(i).writer.close();
clients.get(i).socket.close();
clients.remove(i);
}
if (serverSocket != null) {
serverSocket.close();// 關(guān)閉服務(wù)器端連接
}
listModel.removeAllElements();// 清空用戶列表
isStart = false;
} catch (IOException e) {
e.printStackTrace();
isStart = true;
}
}
// 群發(fā)服務(wù)器消息
public void sendServerMessage(String message) {
for (int i = clients.size() - 1; i >= 0; i--) {
clients.get(i).getWriter().println("服務(wù)器:" + message + "(多人發(fā)送)");
clients.get(i).getWriter().flush();
}
}
// 服務(wù)器線程
class ServerThread extends Thread {
private ServerSocket serverSocket;
private int max;// 人數(shù)上限
// 服務(wù)器線程的構(gòu)造方法
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) {// 如果已達(dá)人數(shù)上限
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@服務(wù)器:對(duì)不起," + user.getName()
+ user.getIp() + ",服務(wù)器在線人數(shù)已達(dá)上限,請(qǐng)稍后嘗試連接!");
w.flush();
// 釋放資源
r.close();
w.close();
socket.close();
continue;
}
ClientThread client = new ClientThread(socket);
client.start();// 開啟對(duì)此客戶端服務(wù)的線程
clients.add(client);
listModel.addElement(client.getUser().getName());// 更新在線列表
contentArea.append(client.getUser().getName()
+ client.getUser().getIp() + "上線!\r\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 為一個(gè)客戶端服務(wù)的線程
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;
}
// 客戶端線程的構(gòu)造方法
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() + "與服務(wù)器連接成功!");
writer.flush();
// 反饋當(dāng)前在線用戶信息
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();
}
// 向所有在線用戶發(fā)送該用戶上線命令
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() {// 不斷接收客戶端的消息,進(jìn)行處理。
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();
// 向所有在線用戶發(fā)送該用戶的下線命令
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());// 更新在線列表
// 刪除此條客戶端服務(wù)線程
for (int i = clients.size() - 1; i >= 0; i--) {
if (clients.get(i).getUser() == user) {
ClientThread temp = clients.get(i);
clients.remove(i);// 刪除此用戶的服務(wù)線程
temp.stop();// 停止這條服務(wù)線程
return;
}
}
} else {
dispatcherMessage(message);// 轉(zhuǎn)發(fā)消息
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 轉(zhuǎn)發(fā)消息
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")) {// 群發(fā)
for (int i = clients.size() - 1; i >= 0; i--) {
clients.get(i).getWriter().println(message + "(多人發(fā)送)");
clients.get(i).getWriter().flush();
}
}
}
}
}
Client_more.java
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_more{
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;// 負(fù)責(zé)接收消息的線程
private Map<String, User> onLineUsers = new HashMap<String, User>();// 所有在線用戶
// 主方法,程序入口
public static void main(String[] args) {
new Client_more();
}
// 執(zhí)行發(fā)送
public void send() {
if (!isConnected) {
JOptionPane.showMessageDialog(frame, "還沒有連接服務(wù)器,無(wú)法發(fā)送消息!", "錯(cuò)誤",
JOptionPane.ERROR_MESSAGE);
return;
}
String message = textField.getText().trim();
if (message == null || message.equals("")) {
JOptionPane.showMessageDialog(frame, "消息不能為空!", "錯(cuò)誤",
JOptionPane.ERROR_MESSAGE);
return;
}
sendMessage(frame.getTitle() + "@" + "ALL" + "@" + message);
textField.setText(null);
}
// 構(gòu)造方法
public Client_more() {
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("吳承潛");
btn_start = new JButton("連接");
btn_stop = new JButton("斷開");
btn_send = new JButton("發(fā)送");
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("服務(wù)器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("消息顯示區(qū)"));
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("客戶機(jī)");
// 更改JFrame的圖標(biāo):
// 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);
// 寫消息的文本框中按回車鍵時(shí)事件
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
send();
}
});
// 單擊發(fā)送按鈕時(shí)事件
btn_send.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
send();
}
});
// 單擊連接按鈕時(shí)事件
btn_start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int port;
if (isConnected) {
JOptionPane.showMessageDialog(frame, "已處于連接上狀態(tài),不要重復(fù)連接!",
"錯(cuò)誤", JOptionPane.ERROR_MESSAGE);
return;
}
try {
try {
port = Integer.parseInt(txt_port.getText().trim());
} catch (NumberFormatException e2) {
throw new Exception("端口號(hào)不符合要求!端口為整數(shù)!");
}
String hostIp = txt_hostIp.getText().trim();
String name = txt_name.getText().trim();
if (name.equals("") || hostIp.equals("")) {
throw new Exception("姓名、服務(wù)器IP不能為空!");
}
boolean flag = connectServer(port, hostIp, name);
if (flag == false) {
throw new Exception("與服務(wù)器連接失敗!");
}
frame.setTitle(name);
JOptionPane.showMessageDialog(frame, "成功連接!");
} catch (Exception exc) {
JOptionPane.showMessageDialog(frame, exc.getMessage(),
"錯(cuò)誤", JOptionPane.ERROR_MESSAGE);
}
}
});
// 單擊斷開按鈕時(shí)事件
btn_stop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!isConnected) {
JOptionPane.showMessageDialog(frame, "已處于斷開狀態(tài),不要重復(fù)斷開!",
"錯(cuò)誤", JOptionPane.ERROR_MESSAGE);
return;
}
try {
boolean flag = closeConnection();// 斷開連接
if (flag == false) {
throw new Exception("斷開連接發(fā)生異常!");
}
JOptionPane.showMessageDialog(frame, "成功斷開!");
} catch (Exception exc) {
JOptionPane.showMessageDialog(frame, exc.getMessage(),
"錯(cuò)誤", JOptionPane.ERROR_MESSAGE);
}
}
});
// 關(guān)閉窗口時(shí)事件
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (isConnected) {
closeConnection();// 關(guān)閉連接
}
System.exit(0);// 退出程序
}
});
}
/**
* 連接服務(wù)器
*
* @param port
* @param hostIp
* @param name
*/
public boolean connectServer(int port, String hostIp, String name) {
// 連接服務(wù)器
try {
socket = new Socket(hostIp, port);// 根據(jù)端口號(hào)和服務(wù)器ip建立連接
writer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
// 發(fā)送客戶端用戶基本信息(用戶名和ip地址)
sendMessage(name + "@" + socket.getLocalAddress().toString());
// 開啟接收消息的線程
messageThread = new MessageThread(reader, textArea);
messageThread.start();
isConnected = true;// 已經(jīng)連接上了
return true;
} catch (Exception e) {
textArea.append("與端口號(hào)為:" + port + " IP地址為:" + hostIp
+ " 的服務(wù)器連接失敗!" + "\r\n");
isConnected = false;// 未連接上
return false;
}
}
/**
* 發(fā)送消息
*
* @param message
*/
public void sendMessage(String message) {
writer.println(message);
writer.flush();
}
/**
* 客戶端主動(dòng)關(guān)閉連接
*/
@SuppressWarnings("deprecation")
public synchronized boolean closeConnection() {
try {
sendMessage("CLOSE");// 發(fā)送斷開連接命令給服務(wù)器
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;
// 接收消息線程的構(gòu)造方法
public MessageThread(BufferedReader reader, JTextArea textArea) {
this.reader = reader;
this.textArea = textArea;
}
// 被動(dòng)的關(guān)閉連接
public synchronized void closeCon() throws Exception {
// 清空用戶列表
listModel.removeAllElements();
// 被動(dòng)的關(guān)閉連接釋放資源
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
if (socket != null) {
socket.close();
}
isConnected = false;// 修改狀態(tài)為斷開
}
public void run() {
String message = "";
while (true) {
try {
message = reader.readLine();
StringTokenizer stringTokenizer = new StringTokenizer(
message, "/@");
String command = stringTokenizer.nextToken();// 命令
if (command.equals("CLOSE"))// 服務(wù)器已關(guān)閉命令
{
textArea.append("服務(wù)器已關(guān)閉!\r\n");
closeCon();// 被動(dòng)的關(guān)閉連接
return;// 結(jié)束線程
} 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")) {// 人數(shù)已達(dá)上限
textArea.append(stringTokenizer.nextToken()
+ stringTokenizer.nextToken() + "\r\n");
closeCon();// 被動(dòng)的關(guān)閉連接
JOptionPane.showMessageDialog(frame, "服務(wù)器緩沖區(qū)已滿!", "錯(cuò)誤",
JOptionPane.ERROR_MESSAGE);
return;// 結(jié)束線程
} else {// 普通消息
textArea.append(message + "\r\n");
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- java socket實(shí)現(xiàn)聊天室 java實(shí)現(xiàn)多人聊天功能
- java編程實(shí)現(xiàn)多人聊天室功能
- Java基于Tcp/ip連接的多人交互聊天室
- java使用MulticastSocket實(shí)現(xiàn)基于廣播的多人聊天室
- Java SE實(shí)現(xiàn)多人聊天室功能
- Java NIO Selector用法詳解【含多人聊天室實(shí)例】
- java實(shí)現(xiàn)多人聊天工具(socket+多線程)
- Java多線程實(shí)現(xiàn)多人聊天室功能
- Java基于中介者模式實(shí)現(xiàn)多人聊天室功能示例
- java實(shí)現(xiàn)多人聊天系統(tǒng)
相關(guān)文章
SpringCloud中的Hystrix保護(hù)機(jī)制詳解
這篇文章主要介紹了SpringCloud中的Hystrix保護(hù)機(jī)制詳解,Hystrix,英文意思是豪豬,全身是刺,看起來(lái)就不好惹,是一種保護(hù)機(jī)制,Hystrix也是Netflix公司的一款組件,需要的朋友可以參考下2023-12-12
SpringMVC框架和SpringBoot項(xiàng)目中控制器的響應(yīng)結(jié)果深入分析
這篇文章主要介紹了SpringMVC框架和SpringBoot項(xiàng)目中控制器的響應(yīng)結(jié)果,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12
Java實(shí)現(xiàn)自定義Excel數(shù)據(jù)排序的方法詳解
通常,我們可以在Excel中對(duì)指定列數(shù)據(jù)執(zhí)行升序或者降序排序,在需要自定義排序情況下,我們也可以自行根據(jù)排序需要編輯數(shù)據(jù)排列順序。本文將通過(guò)Java應(yīng)用程序來(lái)實(shí)現(xiàn)如何自定義排序,需要的可以參考一下2022-09-09
SpringSecurity默認(rèn)登錄頁(yè)的使用示例教程
Spring 是非常流行和成功的 Java 應(yīng)用開發(fā)框架,Spring Security 正是 Spring 家族中的成員,Spring Security 基于 Spring 框架,提供了一套 Web 應(yīng)用安全性的完整解決方案,本文給大家介紹SpringSecurity的默認(rèn)登錄頁(yè)的使用教程,感興趣的朋友一起看看吧2023-12-12
詳解JavaWeb過(guò)濾器 Filter問(wèn)題解決
過(guò)濾器就是對(duì)事物進(jìn)行過(guò)濾的,在Web中的過(guò)濾器,當(dāng)然就是對(duì)請(qǐng)求進(jìn)行過(guò)濾,我們使用過(guò)濾器,就可以對(duì)請(qǐng)求進(jìn)行攔截,然后做相應(yīng)的處理,實(shí)現(xiàn)許多特殊功能,今天主要給大家講解JavaWeb過(guò)濾器 Filter問(wèn)題解決,感興趣的朋友一起看看吧2022-10-10
詳解Spring?Boot中@PostConstruct的使用示例代碼
在Java中,@PostConstruct是一個(gè)注解,通常用于標(biāo)記一個(gè)方法,它表示該方法在類實(shí)例化之后(通過(guò)構(gòu)造函數(shù)創(chuàng)建對(duì)象之后)立即執(zhí)行,這篇文章主要介紹了詳解Spring?Boot中@PostConstruct的使用,需要的朋友可以參考下2023-09-09
springboot整合JPA訪問(wèn)Mysql的實(shí)現(xiàn)方法
本文主要介紹了springboot整合JPA訪問(wèn)Mysql的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
淺談springboot @Repository與@Mapper的區(qū)別
本文主要介紹了淺談springboot @Repository與@Mapper的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03

