基于java TCP实现网络通信聊天室《建议收藏附完整源码》
🍅 作者主頁:Java李楊勇?
🍅 簡(jiǎn)介:Java領(lǐng)域優(yōu)質(zhì)創(chuàng)作者🏆、Java李楊勇公號(hào)作者? ?簡(jiǎn)歷模板、學(xué)習(xí)資料、面試題庫、技術(shù)互助【關(guān)注我,都給你】
🍅 歡迎點(diǎn)贊 👍 收藏 ?留言 📝? ?
🍅 ?文末獲取源碼聯(lián)系方式?📝??
1.1 前言
在信息化社會(huì)的今天,網(wǎng)絡(luò)飛速發(fā)展,人們對(duì)網(wǎng)絡(luò)的依賴越來越多,越來越離不開網(wǎng) 絡(luò),由此而產(chǎn)生的聊天工具越來越多,類似 MSN、QQ,網(wǎng)絡(luò)聊天時(shí)一類的聊天系統(tǒng)的發(fā)展日 新月異,因此產(chǎn)生了制作一個(gè)類似 QQ的網(wǎng)絡(luò)聊天工具的想法,且通過制作該程序還能更好 的學(xué)習(xí)網(wǎng)絡(luò)軟件編程知識(shí)。 網(wǎng)絡(luò)編程的目的就是指直接或間接地通過網(wǎng)絡(luò)協(xié)議與其他計(jì)算機(jī)進(jìn)行通訊。 網(wǎng)編程中有兩 個(gè)主要的問題, 一個(gè)是如何準(zhǔn)確的定位網(wǎng)絡(luò)上一臺(tái)或多臺(tái)主機(jī), 另一個(gè)就是找到主機(jī)后如何 可靠高效的進(jìn)行數(shù)據(jù)傳輸。 在 TCP/IP 協(xié)議中 IP 層主要負(fù)責(zé)網(wǎng)絡(luò)主機(jī)的定位,
數(shù)據(jù)傳輸?shù)穆?由,由 IP 地址可以唯一地確定 Internet 上的一臺(tái)主機(jī)。 而 TCP層則提供面向應(yīng)用的可靠的 或非可靠的數(shù)據(jù)傳輸機(jī)制,這是網(wǎng)絡(luò)編程的主要對(duì)象,一般不需要關(guān)心 IP 層是如何處理數(shù) 據(jù)的。 目前較為流行的網(wǎng)絡(luò)編程模型是客戶機(jī)
/ 服務(wù)器( C/S)結(jié)構(gòu)。 即通信雙方一方作為服 務(wù)器等待客戶提出請(qǐng)求并予以響應(yīng)。 客戶則在需要服務(wù)時(shí)向服務(wù)器提出申請(qǐng)。
服務(wù)器一般作 為守護(hù)進(jìn)程始終運(yùn)行, 監(jiān)聽網(wǎng)絡(luò)端口, 一旦有客戶請(qǐng)求, 就會(huì)啟動(dòng)一個(gè)服務(wù)進(jìn)程來響應(yīng)該客 戶,同時(shí)自己繼續(xù)監(jiān)聽服務(wù)端口,使后來的客戶也得到響應(yīng)的服務(wù)。
1.2 設(shè)計(jì)要求
本課程設(shè)計(jì)的目標(biāo)是利用套接字 socket ()設(shè)計(jì)一個(gè)聊天程序,該程序基于 C/S 模式, 客戶機(jī)器向服務(wù)器發(fā)聊天請(qǐng)求,服務(wù)器應(yīng)答并能顯示客戶機(jī)發(fā)過來的信息。
1.3 設(shè)計(jì)目的
通過設(shè)計(jì)一個(gè)網(wǎng)絡(luò)聊天程序,對(duì)套接字、數(shù)據(jù)報(bào)通訊、 URL、與 URLConnectiom 的相關(guān)知 識(shí)有詳細(xì)的了解和充分的認(rèn)識(shí)。能將相關(guān)的只是運(yùn)用到相關(guān)的實(shí)踐中去。
1.4 功能實(shí)現(xiàn)
聊天室共分為客戶端和服務(wù)端兩部分,
服務(wù)器程序主要負(fù)責(zé)偵聽客戶端發(fā)來的消息,
客戶 端需要登錄到相應(yīng)的服務(wù)器才可以實(shí)現(xiàn)正常的聊天功能。
服務(wù)器的主要功能有
1) 在特定端口上進(jìn)行偵聽,等待客戶連接
2) 用戶可以配置服務(wù)器的監(jiān)聽端口3) 向已經(jīng)連接服務(wù)器的客戶發(fā)送系統(tǒng)消息
5) 當(dāng)停止服務(wù)時(shí),斷開所有用戶的連接
客戶端的主要功能
1) 連接到已經(jīng)開啟聊天服務(wù)的服務(wù)端
2) 用戶可以配置要連接服務(wù)器端的 ip 地址和端口號(hào)
3) 用戶可以配置連接后顯示的用戶名
4) 當(dāng)服務(wù)器開啟時(shí)。用戶可以隨時(shí)登陸
5) 用戶可以向所有人或一個(gè)人發(fā)送消息
1.5?知識(shí)基礎(chǔ)
應(yīng)用到的java知識(shí)點(diǎn)有:
1. Thread 線程
線程池,線程啟動(dòng),接口等。客戶端,服務(wù)器端都用到了線程
2. Socket
使用了socket進(jìn)行端口監(jiān)聽和數(shù)據(jù)傳遞
new Socket("localhost",port);3. Swing圖形化
簡(jiǎn)單的按鈕,輸入框,彈框等
4. 數(shù)據(jù)流
字符流包裝、緩沖字符輸出流包裝、
PrintWrite(new OutputStream(new socket(".."),"UTF-8"),true)部分代碼:
定義服務(wù)器端的界面,添加事件偵聽與事件處理。調(diào)用 start類?Socket方法來實(shí)現(xiàn) 服務(wù)端用戶上線與下線的偵聽, 調(diào)用 Socket類來實(shí)現(xiàn)服務(wù)器端的消息的 收發(fā)。
package chat;import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;/*** 聊天室服務(wù)端* @author 李楊勇**/ public class Server {//運(yùn)行在服務(wù)端的Socket 用來接收客戶端的連接。 private ServerSocket server;//線程池private ExecutorService threadPool;//存放所有客戶端輸出流的共享集合private List<PrintWriter> allOut;/*** 構(gòu)造方法,用來初始化服務(wù)端*/public Server(){try {/** 初始化共享集合*/allOut = new ArrayList<PrintWriter>();/** 讀取配置文件* java.util.Properties* */Properties properties = new Properties();/** void load(InputStream in)* 該方法用于讀取給定的流中的數(shù)據(jù),然后進(jìn)行解析* * 我們可以使用FileInputStream這個(gè)流來讀取我們* 定義的配置文件config.properties,所以我們可以* 創(chuàng)建這個(gè)流,然后將該流作為參數(shù)傳給load方法。* 這樣Properties就可以通過FileInputStream讀取* 我們的配置文件了。*/FileInputStream fis = new FileInputStream("config.properties");properties.load(fis);//獲取服務(wù)端端口號(hào)/** String getProperty(String key)* 給定配置文件中等號(hào)左面的內(nèi)容,可以獲取對(duì)應(yīng)的* 值* serverport=8088*/String port = properties.getProperty("serverport");System.out.println("服務(wù)端口:"+port);/** 初始化ServerSocket時(shí)要傳入一個(gè)參數(shù)* 該參數(shù)就是服務(wù)端對(duì)外開啟的服務(wù)端口* 客戶端就是通過該端口與服務(wù)端進(jìn)行連接的*/server = new ServerSocket(Integer.parseInt(port));/** 獲取線程的數(shù)量阿薩德*/String threadCount = properties.getProperty("threadcount");System.out.println("線程池線程數(shù)量:"+threadCount);/** 初始化線程池*/threadPool = Executors.newFixedThreadPool(Integer.parseInt(threadCount));} catch (Exception e) {e.printStackTrace();}}/*** 向共享集合中添加一個(gè)輸出流* @param out*/public synchronized void addOut(PrintWriter out){allOut.add(out);}/*** 從共享集合中刪除給定的輸出流* @param out*/public synchronized void removeOut(PrintWriter out){allOut.remove(out);}/*** 遍歷共享集合中的所有輸出流,將給定的消息發(fā)送給所有* 的客戶端* @param message*/public synchronized void sendMessageToAllClient(String message){for(PrintWriter out : allOut){out.println(message);}}/*** 服務(wù)端開始工作的方法*/public void start(){try {/** Socket accept()* 該方法是ServerSocket開始監(jiān)聽8088端口,這個(gè)方法* 是一個(gè)阻塞方法,直到一個(gè)客戶端連接為止,若客戶端* 連接了,會(huì)返回一個(gè)Socket,這個(gè)Socket就是用來與* 該客戶端進(jìn)行通訊的。*/while(true){System.out.println("等待一個(gè)客戶端連接...");Socket socket = server.accept();System.out.println("一個(gè)客戶端連接了!");/** 啟動(dòng)一個(gè)線程,并將剛剛連接的客戶端的Socket* 傳給它,讓它去處理與這個(gè)客戶端的交互。*/ClientHandler clientHandler= new ClientHandler(socket); // Thread t = new Thread(clientHandler); // t.start();threadPool.execute(clientHandler);}} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) {Server server = new Server();server.start();}/*** 該內(nèi)部類是為服務(wù)端服務(wù)的。用來與一個(gè)客戶端進(jìn)行* 交互的。* @author 李楊勇*/class ClientHandler implements Runnable{/** 該線程用來交互的客戶端的Socket*/private Socket socket;/** 該客戶端的昵稱*/private String nickName;public ClientHandler(Socket socket){this.socket = socket;/** 獲取遠(yuǎn)程計(jì)算機(jī)的地址信息*/InetAddress address = socket.getInetAddress();//獲取遠(yuǎn)程計(jì)算機(jī)的地址String add = address.getHostAddress();System.out.println(add+"上線了!");}public void run() {PrintWriter pw = null;try {/** 通過Socket獲取輸出流,用于將消息發(fā)送給* 客戶端*/OutputStream out = socket.getOutputStream();OutputStreamWriter osw= new OutputStreamWriter(out,"UTF-8");pw = new PrintWriter(osw,true);//將該客戶端的輸出流放入共享集合中addOut(pw);/** InputStream getInputStream()* Socket的該方法用來獲取遠(yuǎn)程計(jì)算機(jī)發(fā)送過來的數(shù)據(jù)*/InputStream in = socket.getInputStream();InputStreamReader isr= new InputStreamReader(in,"UTF-8");BufferedReader br = new BufferedReader(isr);/** 首先讀取一行字符串,因?yàn)榭蛻舳税l(fā)送過來的第一* 行字符串是該客戶端的昵稱,讀取到后將其設(shè)置到* 屬性nickName上*/nickName = br.readLine();/** 廣播,該用戶上線了*/sendMessageToAllClient("["+nickName+"]上線了");//讀取客戶端發(fā)送過來的一行字符串/** 使用BufferedReader的readLine方法讀取客戶端發(fā)送* 過來的一行字符串時(shí),由于客戶端所使用的操作系統(tǒng)* 不同,這里在客戶端與服務(wù)端斷開連接后,該方法的* 反應(yīng)是不同的。*/String message = null;while((message = br.readLine())!=null){//將讀取到的內(nèi)容轉(zhuǎn)發(fā)給所有客戶端sendMessageToAllClient(nickName+"說:"+message);} } catch (Exception e) {} finally{//將該客戶端的輸出流從共享集合中刪除removeOut(pw);//廣播,通知所有客戶端該用戶下線了sendMessageToAllClient("["+nickName+"]下線了.");/** 將該客戶端的socket關(guān)閉。* 關(guān)閉socket同時(shí)也就將使用它獲取的輸入流與* 輸出流關(guān)掉了。*/try {socket.close();} catch (IOException e) {}}}}}功能實(shí)現(xiàn)截圖:
首先啟動(dòng)server服務(wù):
?
?然后啟動(dòng)client:
client可以啟動(dòng)多個(gè)
?
?
這樣一個(gè)簡(jiǎn)單的基于Java TCP模擬的聊天室完成了?
課程總結(jié):
通過本次課程設(shè)計(jì)是我對(duì)網(wǎng)絡(luò)通信的知識(shí)有了更深的了解。 加深了對(duì) TCP/UDP協(xié)議具體 連接過程的理解。同時(shí)對(duì)套接字、數(shù)據(jù)報(bào)通訊、 URL、與 URLConnectiom 的相關(guān)知識(shí)有了充 分的認(rèn)識(shí)。并將這些知識(shí)運(yùn)用到具體的案例中去。本次課程設(shè)計(jì)不僅運(yùn)用到套接字的知識(shí), 同時(shí)運(yùn)用到 java 中的 GUI 編程,在設(shè)計(jì)框架中運(yùn)用到各種組件與布局,通過服務(wù)器和客戶 端主框架的設(shè)計(jì), 對(duì) GUI編程中的各種組件和布局有了更清晰地了解。 將書本上所學(xué)的知識(shí)成功運(yùn)用到實(shí)踐中去。 通過本次課程設(shè)計(jì)使自己對(duì)在 Java 中所學(xué)的 Swing 組件, 面板容器, 事件處理,線程的創(chuàng)建、同步,輸入輸出處理,內(nèi)部類,異常處理,和網(wǎng)絡(luò)通信的知識(shí)有了 一個(gè)復(fù)習(xí)和運(yùn)用。培養(yǎng)了自己的編程能力,將學(xué)習(xí)和實(shí)踐結(jié)合起來。 在 Java 的學(xué)習(xí)過程中,往往程序自己看得懂,但是需把所學(xué)知識(shí)運(yùn)用到實(shí)踐中去時(shí),往 往會(huì)遇到這樣那樣的問題, 本次課程設(shè)計(jì)極大了鍛煉了自己的動(dòng)手能力, 同時(shí)也使自己明白 了只有動(dòng)手做才會(huì)將課本上的知識(shí)變?yōu)樽约旱摹?只有自己參與實(shí)踐, 才能發(fā)現(xiàn)問題, 解決問題,在解決問題的過程中提升自己的能力。 希望自己以后能更多的將理論結(jié)合實(shí)踐,再動(dòng)手 的過程中提高自己的編程能力和軟件設(shè)計(jì)能力。
代碼獲取:
java TCP網(wǎng)絡(luò)通信聊天室(源碼+報(bào)告論文6000字)
相關(guān)Java實(shí)戰(zhàn)項(xiàng)目精彩推送
基于java ssm springboot+VUE疫情防疫系統(tǒng)系統(tǒng)前后端分離設(shè)計(jì)和實(shí)現(xiàn)
基于java springboot+mybatis電影售票網(wǎng)站管理系統(tǒng)前臺(tái)+后臺(tái)設(shè)計(jì)和實(shí)現(xiàn)
基于java ssm springboot+mybatis酒莊內(nèi)部管理系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)
基于JAVA springboot+mybatis智慧生活分享平臺(tái)設(shè)計(jì)和實(shí)現(xiàn)
基于Java springboot+vue+redis前后端分離家具商城平臺(tái)系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)
基于JAVA SSM springboot實(shí)現(xiàn)的抗疫物質(zhì)信息管理系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)
查看更多博主首頁更多實(shí)戰(zhàn)項(xiàng)目 >>>
Java李楊勇?
獲取源碼:
總體來說這個(gè)項(xiàng)目功能相對(duì)還是比較簡(jiǎn)單優(yōu)秀的、適合初學(xué)者作為課程設(shè)計(jì)和畢業(yè)設(shè)計(jì)參考?
查看下方微信公眾號(hào)獲取聯(lián)系方式~
精彩系列推薦
Java畢設(shè)項(xiàng)目精品實(shí)戰(zhàn)案例《100套》
HTML5大作業(yè)實(shí)戰(zhàn)案例《100套》
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的基于java TCP实现网络通信聊天室《建议收藏附完整源码》的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 智能家居中语音识别算法研究_语音识别研究
- 下一篇: Tomcat 中文路径乱码