Java多線程實(shí)現(xiàn)多人聊天室功能
本文為大家分享了Java多線程實(shí)現(xiàn)多人聊天室功能的具體代碼,供大家參考,具體內(nèi)容如下
1.實(shí)驗(yàn)?zāi)康模?/h3>
編寫一個(gè) Java 應(yīng)用程序,實(shí)現(xiàn)圖形界面多人聊天室(多線程實(shí)現(xiàn)),要求聊天室窗口標(biāo)題是 “歡迎使用 XXX 聊天室應(yīng)用”,其中 XXX 是自己的班級(jí)姓名學(xué)號(hào),如“軟件 171 張三 1234”。
2.實(shí)驗(yàn)代碼:
服務(wù)端程序代碼:
ServerChar.java
package works;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class ServerChat {
//定義Map集合用于存儲(chǔ)用戶的Socket以及用戶的名字 key:Socket Value:用戶名
public final static Map<Socket,String> socketsMaps = Collections.synchronizedMap(new HashMap<Socket,String>());
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
// 創(chuàng)建服務(wù)端套接字
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("------服務(wù)端暴露-------");
while (true) {
// 監(jiān)聽客戶端套接字,若有客戶端連接,則代碼不會(huì)往下執(zhí)行,否則會(huì)堵塞在此處。
Socket socket = serverSocket.accept();
// 開啟線程,用于讀取客戶端發(fā)送的信息,并轉(zhuǎn)發(fā)給每一個(gè)客戶端
new ThreadServer(socket).start();
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
class ThreadServer extends Thread {
private Socket socket;
ThreadServer(){};
ThreadServer(Socket socket)
{
this.socket = socket;
}
@Override
public void run() {
try {
while(true)
{
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
String data = dataInputStream.readUTF();
if(data.startsWith("①②③④")&&data.endsWith("①②③④"))
{
//發(fā)送過來的是用戶名
//將Socket以及用戶名字都存放在Map集合中
ServerChat.socketsMaps.put(socket, data.replace("①②③④",""));
//獲取所有的key(Socket),將所有用戶的名字發(fā)送至客戶端
Set<Socket> sockets = ServerChat.socketsMaps.keySet();
//獲取所有的用戶的名字,將這些名字拼裝成一個(gè)字符串
Collection<String> names = ServerChat.socketsMaps.values();
StringBuffer sbf = new StringBuffer();
for(String userName :names)
{
sbf.append(userName).append(",");
}
System.out.println("sbf:"+sbf.toString());
for(Socket soc:sockets)
{
DataOutputStream dataOutputStream = new DataOutputStream(soc.getOutputStream());
dataOutputStream.writeUTF("①②③④"+sbf.toString()+"①②③④");
dataOutputStream.flush();
}
}
else{
//發(fā)送過來的是聊天信息
//獲取所有的key(Socket),將所有用戶的名字發(fā)送至客戶端
Set<Socket> sockets = ServerChat.socketsMaps.keySet();
//將聊天信息廣播出去
for(Socket soc:sockets)
{
DataOutputStream dataOutputStream = new DataOutputStream(soc.getOutputStream());
dataOutputStream.writeUTF("[ "+ServerChat.socketsMaps.get(socket)+" ]說:"+data);
dataOutputStream.flush();
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客戶端程序代碼:
ClientChar.java
package works;
import java.awt.BorderLayout;
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.Box;
import javax.swing.BoxLayout;
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.JTextArea;
public class ClientChat {
private JFrame mainWin = new JFrame("聊天窗口");
// 消息展示框
private JTextArea displayTa = new JTextArea(14, 40);
// 在線用戶名稱展示框
private DefaultListModel<String> userListModel = new DefaultListModel<>();
private JList<String> userList = new JList<>(userListModel);
// 消息發(fā)送框
private JTextArea inputTF = new JTextArea(4, 40);
// 消息按鈕
private JButton sendBn = new JButton("發(fā)送");
// 用戶記錄當(dāng)前聊天用戶名
private String curUser;
public static void main(String[] args) {
new ClientChat().init();
}
private void init() {
try {
// 通過彈出對(duì)話框獲取用戶輸入的用戶名
String userName = JOptionPane.showInputDialog(mainWin, "請(qǐng)輸入您的用戶名:");
// 把用戶輸入的用戶名,賦給curUser
curUser = userName;
mainWin.setTitle(curUser + "的聊天窗口");
// 創(chuàng)建套接字
Socket socket = new Socket("192.168.193.1", 9999);
// 向服務(wù)器聲明
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
//發(fā)送用戶名到服務(wù)端
dataOutputStream.writeUTF("①②③④"+userName+"①②③④");
dataOutputStream.flush();
// 開啟線程,用于讀取服務(wù)器發(fā)送的信息
new ThreadClient(socket, this).start();
JPanel bottomPanel = new JPanel();
// 將消息框和按鈕添加到窗口的底端
mainWin.add(bottomPanel, BorderLayout.SOUTH);
bottomPanel.add(inputTF);
bottomPanel.add(sendBn);
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 獲取用戶發(fā)送的消息
String message = inputTF.getText();
sendSms(message,socket);
}
};
// 給發(fā)送消息按鈕綁定點(diǎn)擊事件監(jiān)聽器
sendBn.addActionListener(listener);
JPanel centerPanel = new JPanel();
// 將展示消息區(qū)centerPanel添加到窗口的中間
mainWin.add(centerPanel);
// 讓展示消息區(qū)可以滾動(dòng)
centerPanel.add(new JScrollPane(displayTa));
displayTa.setEditable(false);
// 用戶列表和是否私聊放到窗口的最右邊
Box rightBox = new Box(BoxLayout.Y_AXIS);
userList.setFixedCellWidth(60);
userList.setVisibleRowCount(13);
rightBox.add(new JLabel("用戶列表:"));
rightBox.add(new JScrollPane(userList));
centerPanel.add(rightBox);
// 關(guān)閉窗口退出當(dāng)前程序
mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainWin.pack(); // swing加上這句就可以擁有關(guān)閉窗口的功能
mainWin.setVisible(true);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
//點(diǎn)擊發(fā)送后將消息發(fā)送到服務(wù)器
protected void sendSms(String sms, Socket socket) {
try {
//發(fā)送聊天消息到服務(wù)端
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeUTF(sms);
dataOutputStream.flush();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public DefaultListModel<String> getUserListModel() {
return userListModel;
}
public JTextArea getDisplayTa() {
return displayTa;
}
public JTextArea getInputTF()
{
return inputTF;
}
}
// 定義線程類,用來讀取服務(wù)器發(fā)送的信息
class ThreadClient extends Thread {
private Socket socket;
private ClientChat clientChat;
ThreadClient() {
}
ThreadClient(Socket socket, ClientChat clientChat) {
this.socket = socket;
this.clientChat = clientChat;
}
@Override
public void run() {
try {
while (true) {
DataInputStream DataInputStream = new DataInputStream(socket.getInputStream());
String message = DataInputStream.readUTF();
if(message.startsWith("①②③④")&&message.endsWith("①②③④"))
{
//說明信息是用戶名
String[] names = message.replace("①②③④","").split(",");
// 將用戶列表先清空
clientChat.getUserListModel().clear();
for (int i = 0; i < names.length; ++i) {
clientChat.getUserListModel().addElement(names[i]);
}
}
else
{
//說明是聊天信息,將聊天信息放在displayTa中
clientChat.getInputTF().setText("");
clientChat.getDisplayTa().append(message+"\t\n");
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.實(shí)驗(yàn)截圖
先開啟服務(wù)端

再開啟客戶端

聊天過程

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- java socket實(shí)現(xiàn)聊天室 java實(shí)現(xiàn)多人聊天功能
- 基于java編寫局域網(wǎng)多人聊天室
- 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)多人聊天系統(tǒng)
相關(guān)文章
java計(jì)算兩個(gè)時(shí)間相差天數(shù)的方法匯總
這篇文章主要介紹了java計(jì)算兩個(gè)時(shí)間相差天數(shù)的方法,感興趣的小伙伴們可以參考一下2015-11-11
Java中的三種標(biāo)準(zhǔn)注解和四種元注解說明
這篇文章主要介紹了Java中的三種標(biāo)準(zhǔn)注解和四種元注解說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
SpringBoot擴(kuò)展點(diǎn)EnvironmentPostProcessor實(shí)例詳解
這篇文章主要介紹了SpringBoot擴(kuò)展點(diǎn)EnvironmentPostProcessor的相關(guān)知識(shí),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04
Java如何生成4位、6位隨機(jī)數(shù)短信驗(yàn)證碼(高效實(shí)現(xiàn))
這篇文章主要介紹了Java如何生成4位、6位隨機(jī)數(shù)短信驗(yàn)證碼(高效實(shí)現(xiàn)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
Java使用新浪微博API通過賬號(hào)密碼方式登陸微博的實(shí)例
這篇文章主要介紹了Java使用新浪微博API通過賬號(hào)密碼方式登陸微博的實(shí)例,一般來說第三方App都是采用OAuth授權(quán)認(rèn)證然后跳轉(zhuǎn)之類的方法,而本文所介紹的賬號(hào)方式則更具有自由度,需要的朋友可以參考下2016-02-02
Maven配置單倉庫與多倉庫的實(shí)現(xiàn)(Nexus)
本文主要介紹了Maven配置單倉庫與多倉庫的實(shí)現(xiàn)(Nexus),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
IDEA?mybatis?Mapper.xml報(bào)紅的最新解決辦法
這篇文章主要介紹了IDEA?mybatis?Mapper.xml報(bào)紅的解決辦法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04

