激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java Socket實現聊天室附1500行源代碼

Java Socket實現聊天室附1500行源代碼

2022-02-22 00:43碼農C風 Java教程

Socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。本篇文章手把手帶你通過Java Socket來實現自己的聊天室,大家可以在過程中查缺補漏,溫故而知新

Java養成計劃(打卡第31,2天)

內容管理:Sockect聊天室的實現

Java界面 使用了各種組件,對于這部分不了解的不用擔心,目前掌握一個大概就OK

項目需求分析

需要完成一個簡單聊天工具的界面及功能,實現服務器中轉下的多客戶端之間的通信,系統完成的功能有

  • 程序啟動后能看到當前有那些機器上線,可彈出對話聊天框,可以在其中編輯要發送的聊天信息,并進行發送
  • 一旦某個網內的機器上線了,可即時通知,并能更新用戶界面的用戶列表
  • 雙擊某個列表項時,可彈出對話聊天框,可以在其中編輯要發送的信息并發送
  • 聊天界面人性化,下面時發送框,上面有已有聊天記錄,并借助滾動條看到當次所有聊天記錄
  • 當有人向本機器發送消息時,可顯示用戶接收到的信息,并且顯示是誰所發,同時進行信息的回復

基礎分析

首先這是一個聊天工具,使用的是C/S結構,要模擬就要使用net的Scocket和ServerSocket模擬客戶端和服務端

這里綜合運用了多種知識,已經不再是簡單的java SE知識,其中界面編程占據主要代碼,這里可以貼幾張圖看看效果,這是我肝了2天才肝完的,這里已經可以實現多態設備的連接

分為3個包

Sever包主要是服務器的相關代碼,主要是實現與用戶的交互

Dao包是模擬的數據庫包,存儲所有的用戶信息,實現增刪改的操作

Client是客戶代碼包,只要在電腦上運行這里的代碼,就可以出現客戶端界面,約定好ip和端口號就可以通信了。這里就真正實現了客戶端型軟件,只是軟件功能簡單,可以使用web編程實現另外一種架構
可以來看一下界面

Java Socket實現聊天室附1500行源代碼

再來看一下客戶端和服務端的交流

Java Socket實現聊天室附1500行源代碼

項目部分代碼摘要

Dao的鏈表存儲實現

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package Dao;
 
/**
 * 演示程序為了簡化就不用數據庫存儲,使用單鏈表完成數據庫各項功能
 * 這里一定要寫測試代碼檢查各項功能是否可用
 * 最開開始我測試了add,del,find功能,卻沒有測試getCount功能,結果存在問題,后面突然放開測試才發現錯誤
 */
public class UserLinkList {
    private  Node head;
    private int count;
 
    public boolean addUser(Node client)
    {
        if(head == null)
        {//頭節點也存儲數據
            head = client;
            count++;
            return true;
        }
        else {
            Node p = head;
            for(;p.next != null;p = p.next);
            {
                p.next = client;
                count++;
                return true;
            }
        }
    }
    
    public int getCount() {
        return count;
    }
    
    public Node findUser(String name)
    {
        Node p = head;
        while(p != null )//p.next != null沒有包含最后一個結點
        {
            if(p.username.equals(name))
            {
                return p;
            }
            p = p.next;
        }
        return null;
    }
    
    public Node findUser(int index)
    {
        int pos = 0;
        Node p = head;
        while(p != null&& pos < index)
        {
            p = p.next;
            pos++;
        }
        if(p != null&& pos == index)
        {
            return p;
        }
        return null;
    }
    
    public boolean delUser(Node client)
    {//刪除后長度也要減少
        Node p = head;
        if(p.username.equals(client.username))
        {//刪除頭結點
            head = head.next;
            count--;
            return true;
        }
        while(p != null)
        {//忘記循環了
            if(p.next.username.equals(client.username))
            {
                p.next = p.next.next;
                count--;
                return true;
            }
            p = p.next;
        }
        return false;
    }
    
    /**
     * 這里可以設置一個顯示的方法,供檢查使用
     */
    public void display() {
        Node p = head;
        int pos = 1;
        while(p != null)
        {
            System.out.println("第"+pos + "個用戶"+p.username);
            p = p.next;
            pos++;
        }
    }
}
/* 
    public static void main(String[] args) {//經過測試發現沒有問題,可以正常使用
        Node client1 = new Node();
        client1.username = "張三";
        Node client2 = new Node();
        client2.username = "李四";
        Node client3 = new Node();
        client3.username = "王五";
        //其他的就不測試了,反正該項就可以測試了
        UserLinkList userLinkList = new UserLinkList();//自動初始化
        userLinkList.addUser(client1);
        userLinkList.addUser(client2);
        userLinkList.addUser(client3);
//      userLinkList.display();
        Node node = userLinkList.findUser(0);
        userLinkList.delUser(node);
        userLinkList.display();
        System.out.println(userLinkList.getCount());
    }
*/

現在編寫這段代碼應當是非常簡單的,注意一定要測試

ServerListen

簡單看一下這個監聽線程,可以監聽用戶是否上線

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package Server;
/**
 * @author OMEY-PC
 *本程序的作用是實現服務器偵聽的線程化,其中run方法通過client = new Node();創建一個客戶端對象,通過client.socket = server.accept來設定接口,通過client.input
 *output來建立輸入輸出流
 */
 
import java.io.*;
import java.net.*;
import Dao.*; //連接數據
import javax.swing.*;
 
public class ServerListen extends Thread{
    ServerSocket server;
    JComboBox combobox;
    JTextArea textarea;
    JTextField textfield;
    UserLinkList userLinkList;
    Node client;
    ServerReceive recvThread;
    public boolean isStop;
    /**
     * 聊天服務端的用戶上下線偵聽類
     */
    public ServerListen(ServerSocket server,JComboBox combobox,JTextArea textarea,JTextField textField,UserLinkList userLinkList) {
        this.server = server;
        this.combobox = combobox;
        this.textarea = textarea;
        this.textfield = textField;
        this.userLinkList = userLinkList;
        isStop = false;
    }
    @Override
    public void run() {
        while(!isStop && !server.isClosed())//沒有停止服務
        {
            try {
                client = new Node();
                client.socket = server.accept();//用來指代所連接的客戶端
                client.output = new ObjectOutputStream(client.socket.getOutputStream());
                client.output.flush();
                client.input = new ObjectInputStream(client.socket.getInputStream());
                client.username = (String)client.input.readObject();
                //顯示提示信息
                combobox.addItem(client.username);//改成用戶名
                userLinkList.addUser(client);
                textarea.append("用戶" + client.username+"上線"+"\n");
                textfield.setText("在線用戶"+ userLinkList.getCount()+"人\n");
                
                recvThread = new ServerReceive(textarea,textfield,combobox,client,userLinkList);
                recvThread.start();//啟動線程
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

ServerReceive

該線程實現服務器與用戶之間的信息交互

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package Server;
/**
 * @author OMEY-PC
 *服務器收發消息的類
 */
 
import java.net.ServerSocket;
 
import javax.swing.*;
import Dao.*;
 
public class ServerReceive extends Thread{
    JTextArea textarea;//消息展示域
    JTextField textfield;//文本輸入域
    JComboBox combobox; //復選框
    Node client;//用戶
    UserLinkList userLinkList;
    public boolean isStop;
    public ServerReceive(JTextArea textarea, JTextField textfield, JComboBox combobox, Node client,
            UserLinkList userLinkList) {
        this.textarea = textarea;
        this.textfield = textfield;
        this.combobox = combobox;
        this.client = client;
        this.userLinkList = userLinkList;
        isStop = false;
    }
    
    @Override
    public void run()
    {
        //向所有人發送用戶的列表
        sendUserList();
        while(!isStop && !client.socket.isClosed())
        {
            try {//類型,對誰,狀況,行為,信息
                String type = (String)client.input.readObject();
                if(type.equalsIgnoreCase("聊天信息"))
                {
                    String toSomebody =(String)client.input.readObject();//從客戶端接收信息
                    String status = (String)client.input.readObject();
                    String action = (String)client.input.readObject();
                    String message = (String)client.input.readObject();
                    String msg = client.username+" "+ action + "對"+ toSomebody +" 說 " + message + "\n";//接收的消息
                    if(status.equalsIgnoreCase("悄悄話"))
                    {
                        msg = "[悄悄話]" + msg; //若為悄悄話,就在前面加上標識
                    }
                    textarea.append(msg);
                    if(toSomebody.equalsIgnoreCase("所有人"))
                    {
                        sendToAll(msg);//這里是接受的用戶消息,和之前的向所有人發消息不一樣
                    }
                    else {//向用戶發消息
                        try {
                            client.output.writeObject("聊天信息");
                            client.output.flush();//刷新流
                            client.output.writeObject(msg);
                            client.output.flush();
                        }catch (Exception e) {
                            e.printStackTrace();
                        }
                        Node node = userLinkList.findUser(toSomebody);
                        if(node != null)
                        {
                            node.output.writeObject("聊天信息");
                            node.output.flush();
                            node.output.writeObject(msg);//向選定信息發送信息
                            node.output.flush();//刷新輸出流緩沖區中的信息
                        }
                    }
                }
                else if(type.equalsIgnoreCase("用戶下線"))
                {
                    Node node = userLinkList.findUser(client.username);
                    userLinkList.delUser(node);
                    String msg = "用戶"+ client.username +"下線\n";
                    int count = userLinkList.getCount();
                    combobox.removeAllItems();
                    combobox.addItem("所有人");
                    int i = 0;
                    while(i < count)
                    {
                        node = userLinkList.findUser(i);
                        if(node == null)
                        {
                            i++;
                            continue;
                        }
                        combobox.addItem(node.username);
                        i++;
                    }
                    combobox.setSelectedIndex(0);//選擇第一個,所有人
                    textarea.append(msg);
                    textfield.setText("在線用戶"+ userLinkList.getCount() +"人\n");
                    
                    sendToAll(msg);
                    sendUserList();//重新發送用戶列表
                    break;
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 向所有人發送消息
     */
    public void sendToAll(String msg)
    {
        int count = userLinkList.getCount();
        int i = 0;
        while(i < count)
        {//給用戶列表中的每一個人都發送消息
            Node node = userLinkList.findUser(i);
            if(node == null)
            {
                i++;
                continue;
            }
            try {//輸出流
                node.output.writeObject("聊天信息");
                node.output.flush();
                node.output.writeObject(msg);//聊天消息寫入輸出流(to client)
                node.output.flush();
            }catch (Exception e) {
                e.printStackTrace();
            }
            i++;
        }
    }
    /**
     * 向所有人發送用戶列表
     */
    public void sendUserList() {
        String userList = "";
        int count = userLinkList.getCount();
        int i = 0;
        while(i < count)
        {
            Node node = userLinkList.findUser(i);
            if(node == null)
            {
                i++;
                continue;
            }
            userList += node.username;
            userList += "\n";
            i++;
        }
        i = 0; //給每個人發送消息
        while(i < count)
        {
            Node node = userLinkList.findUser(i);
            if(node == null)
            {
                i++;
                continue;
            }
            try {
                node.output.writeObject("用戶列表");
                node.output.flush();
                node.output.writeObject(userList);
                node.output.flush();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        i++;
    }  
}
/**
 * 本程序可以實現通過線程向所有人發送消息,用戶列表,以及向選定的人發送聊天消息等,主要是是實現服務端收發消息的線程化,其中sendUserList()發送列表,
 * client.input.redObject()獲取客戶端發送到服務端的消息,通sendToAll(),將發送到發送到所有人的信息發送到各個客戶端
 */

再看一下客戶端的ClientReceive

該線程是實現客戶端與系統之間的信息交互,注解豐富

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package Client;
 
import java.io.*;
import java.net.*;
 
import javax.swing.*;
 
public class ClientReceive extends Thread{
    private JComboBox combobox;
    private JTextArea textarea;
    Socket socket;
    ObjectOutputStream output;
    ObjectInputStream input;
    JTextField showStatus;
    public ClientReceive(JComboBox combobox, JTextArea textarea, Socket socket, ObjectOutputStream output,
            ObjectInputStream input, JTextField showStatus) {
        this.combobox = combobox;
        this.textarea = textarea;
        this.socket = socket;
        this.output = output;
        this.input = input;
        this.showStatus = showStatus;
    }
    
    @Override
    public void run() {//從服務端獲得消息
        while(!socket.isClosed())
        {
            try {
                String type = (String)input.readObject();//獲得流,read讀取信息
                if(type.equalsIgnoreCase("系統信息"))
                {
                    String sysmsg = (String)input.readObject();
                    textarea.append("系統信息" + sysmsg);
                }
                else if(type.equalsIgnoreCase("服務關閉"))
                {
                    output.close();
                    input.close();
                    socket.close();
                    textarea.append("服務器已經關閉!\n");
                    break;
                }
                else if(type.equalsIgnoreCase("聊天信息"))
                {
                    String message = (String)input.readObject();
                    textarea.append(message);
                }
                else if(type.equalsIgnoreCase("用戶列表"))
                {
                    String userlist = (String)input.readObject();
                    String[] usernames = userlist.split("\n"); //用換行符分隔
                    combobox.removeAll();//先移出去
                    int i = 0;
                    combobox.addItem("所有人");
                    while(i < usernames.length)
                    {
                        combobox.addItem(usernames[i]);
                        i++;
                    }
                    combobox.setSelectedIndex(0);
                    showStatus.setText("在線用戶"+ usernames.length +" 人");
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

其余的界面的部分就不放出來了,代碼太長,每個都有400多行,如果有興趣,就到我的gitee上去瀏覽,后面會放上地址

項目問題

選擇框中出現的不是用戶名

查找相應模塊發現是因為addItem中添加的時結點,而不是結點中的username,修改后正常

服務端點擊消息發送按鈕沒有反應

查找監聽器部分,發現監聽器監聽該部分代碼寫錯,將button又寫成sysMessage

不能顯示在線人數

查找偵聽線程,啟動客戶端發現拋出異常

Cannot invoke “javax.swing.JTextField.setText(String)” because “this.textfield” is null

textfield為空,查找問題源頭;發現在構造方法中:the assignmen to variable has no effect;這是因為單詞拼寫錯誤,編譯器并沒有報錯

服務端退出時沒有消息

系統報錯

Cannot read field “input” because “node” is null

意識到問題出在鏈表上,系統要求從0開始,而鏈表中的序號是從1開始的,修該鏈表中的findUser中的pos為0就解決

寫這個程序寫了兩天,直接廢了~~

到此這篇關于Java Socket實現聊天室附1500行源代碼的文章就介紹到這了,更多相關Java Socket內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/a23452/article/details/120791330

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 爱逼爱操综合网 | 毛片118极品美女写真 | 亚洲婷婷日日综合婷婷噜噜噜 | 一级免费大片 | 久久国产精品电影 | 狠狠干五月天 | 国产精品亚洲一区二区三区在线观看 | 热99精品视频 | 日本黄色大片免费 | 天天躁狠狠躁夜躁2020挡不住 | 毛片免费大全短视频 | 91懂色| 国产一区视频免费观看 | 国产91精品久久久 | av色哟哟| 成人久久久久久久久久 | 欧美a在线观看 | 日日爱99 | 久久国产中文 | 免费毛片电影 | 污视频在线看 | www69xxxxx| 91一区二区在线观看 | 黄色一级片免费在线观看 | 禁漫天堂久久久久久久久久 | 欧美成年性h版影视中文字幕 | 久久久中精品2020中文 | 国产艳妇av视国产精选av一区 | 精品国产视频一区二区三区 | 91看片在线免费观看 | 国产亚洲在线 | 91成人在线免费观看 | 国产成人在线综合 | 国产精品一区在线观看 | 成人综合在线观看 | 18视频在线观看娇喘 | 凹凸成人精品亚洲精品密奴 | 一本在线高清码电影 | 久久综合精品视频 | 免费看黄色一级大片 | 欧日韩在线视频 |