詳解基于java的Socket聊天程序——初始設(shè)計(jì)(附demo)
寫(xiě)在前面:
可能是臨近期末了,各種課程設(shè)計(jì)接踵而來(lái),最近在csdn上看到2個(gè)一樣問(wèn)答,那就是編寫(xiě)一個(gè)基于socket的聊天程序,正好最近剛用socket做了一些事,出于興趣,自己抽了幾個(gè)晚上的空閑時(shí)間敲了一個(gè),目前僅支持單聊,群聊,文件傳送這些功能。首先,貼出一個(gè)丑丑的程序圖(UI是用java swing寫(xiě)的,這個(gè)早就忘光了,無(wú)奈看著JDK的API寫(xiě)了一個(gè)),如下圖:
服務(wù)端設(shè)計(jì):
服務(wù)端主要有兩個(gè)操作,一是阻塞接收客戶(hù)端的socket并做響應(yīng)處理,二是檢測(cè)客戶(hù)端的心跳,如果客戶(hù)端一段時(shí)間內(nèi)沒(méi)有發(fā)送心跳則移除該客戶(hù)端,由Server創(chuàng)建ServerSocket,然后啟動(dòng)兩個(gè)線(xiàn)程池去處理這兩件事(newFixedThreadPool,newScheduledThreadPool),對(duì)應(yīng)的處理類(lèi)分別是SocketDispatcher、SocketSchedule,其中SocketDispatcher根據(jù)socket不同的請(qǐng)求分發(fā)給不同SocketHandler去處理,而SocketWrapper則是對(duì)socket加了一層外殼包裝,用lastAliveTime記錄socket最新的交互時(shí)間,SocketHolder存儲(chǔ)當(dāng)前跟服務(wù)端交互的socket集合。設(shè)計(jì)如下:
客戶(hù)端設(shè)計(jì):
客戶(hù)端設(shè)計(jì)主要分成兩個(gè)部分,分別是socket通訊模塊設(shè)計(jì)和UI相關(guān)設(shè)計(jì)
客戶(hù)端socket通訊設(shè)計(jì),這里的設(shè)計(jì)其實(shí)跟服務(wù)端的設(shè)計(jì)差不多,不同的是服務(wù)端是接收心跳包,而客戶(hù)端是發(fā)送心跳包,由于客戶(hù)端只與一個(gè)服務(wù)端進(jìn)行通訊(客戶(hù)端之間的通訊也是由服務(wù)端進(jìn)行分發(fā)的),所以這里只使用了一個(gè)大小為2的線(xiàn)程池去處理這兩件事(newFixedThreadPool(2)),對(duì)應(yīng)的處理類(lèi)分別是ReceiveListener、KeepAliveDog,其中ReceiveListener在初始化的時(shí)候傳入一個(gè)Callback作為客戶(hù)端收到服務(wù)端的消息的回調(diào),Callback的默認(rèn)實(shí)現(xiàn)是DefaultCallback,DefaultCallback根據(jù)不同的事件通過(guò)HF分發(fā)給不同Handler去處理,而ClientHolder則是存儲(chǔ)當(dāng)前客戶(hù)端信息,設(shè)計(jì)如下:
UI相關(guān)設(shè)計(jì),這里我不打算自己寫(xiě)UI,畢竟自己寫(xiě)出來(lái)的太丑了,所以后期可能會(huì)叫同學(xué)或朋友幫忙敲一下,所以我將UI的事件處理都交由Action去處理,將UI設(shè)計(jì)和事件響應(yīng)簡(jiǎn)單分離,所有UI繼承JFrame并實(shí)現(xiàn)View接口,上面的Handler實(shí)現(xiàn)類(lèi)通過(guò)Router獲取(存在則直接返回,不存在則創(chuàng)建并存儲(chǔ))指定的UI,View中提供了UI的創(chuàng)建create()、獲取container()、獲取UI中的組件getComponent(),顯示display(),回收trash();ResultWrapper和ResultHolder只是為了創(chuàng)建和存儲(chǔ)聊天選項(xiàng)卡。
Common模塊設(shè)計(jì):
Common模塊主要是數(shù)據(jù)交互,這里使用JSON數(shù)據(jù)進(jìn)行交互,common模塊定義了各類(lèi)交互信息,SendHelper實(shí)現(xiàn)的socket信息的傳送,I18N是語(yǔ)言話(huà),ConstantValue是系統(tǒng)中的配置以及常量(這里常量都是用接口,這個(gè)可能不太好),對(duì)于ReturnMessage擁有一系列的DTO作為其content屬性。
程序入口:
最后給出服務(wù)端和客戶(hù)端的入口程序(完整代碼掛在csdn上,有時(shí)間會(huì)持續(xù)更新,文章最后有地址)
服務(wù)端入口:
package yaolin.chat.server; import java.io.IOException; import java.net.ServerSocket; import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import yaolin.chat.common.ConstantValue; import yaolin.chat.util.LoggerUtil; /** * 服務(wù)器 * @author yaolin */ public class Server { private final ServerSocket server; private final ExecutorService pool; public Server() throws IOException { server = new ServerSocket(ConstantValue.SERVER_PORT); pool = Executors.newFixedThreadPool(ConstantValue.MAX_POOL_SIZE); } public void start() { try { ScheduledExecutorService schedule = Executors.newScheduledThreadPool(1); // Watch dog. Exception?? schedule.scheduleAtFixedRate(new SocketSchedule(), 10, ConstantValue.TIME_OUT, TimeUnit.SECONDS); while (true) { pool.execute(new SocketDispatcher(server.accept())); LoggerUtil.info("ACCEPT A CLIENT AT " + new Date()); } } catch (IOException e) { pool.shutdown(); } } public static void main(String[] args) { try { new Server().start(); } catch (IOException e) { LoggerUtil.error("Server start failed! -> " + e.getMessage(), e); } } }
客戶(hù)端入口:
package yaolin.chat.client; import java.io.IOException; import javax.swing.JOptionPane; import yaolin.chat.client.callback.DefaultCallback; import yaolin.chat.client.view.Router; import yaolin.chat.client.view.impl.RegisterAndLoginView; /** * * @author yaolin * */ public class NiloayChat { public static void main(String[] args) { RegisterAndLoginView v = (RegisterAndLoginView) Router.getView(RegisterAndLoginView.class).create(); try { v.display(); Client client = new Client(new DefaultCallback()); client.start(); ClientHolder.setClient(client); } catch (IOException e) { JOptionPane.showMessageDialog(v.getContentPane(), e.getMessage()); } } }
源碼下載:demo
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- java中UDP簡(jiǎn)單聊天程序?qū)嵗a
- 詳解基于java的Socket聊天程序——客戶(hù)端(附demo)
- java網(wǎng)絡(luò)編程學(xué)習(xí)java聊天程序代碼分享
- java基于TCP協(xié)議實(shí)現(xiàn)聊天程序
- java基于C/S模式實(shí)現(xiàn)聊天程序(客戶(hù)端)
- 詳解基于java的Socket聊天程序——服務(wù)端(附demo)
- java實(shí)現(xiàn)基于Tcp的socket聊天程序
- java實(shí)現(xiàn)簡(jiǎn)單TCP聊天程序
- 基于Java的Socket多客戶(hù)端Client-Server聊天程序的實(shí)現(xiàn)
- 用Java實(shí)現(xiàn)聊天程序
相關(guān)文章
在jmeter的beanshell中用java獲取系統(tǒng)當(dāng)前時(shí)間的簡(jiǎn)單實(shí)例
這篇文章介紹了在jmeter的beanshell中用java獲取系統(tǒng)當(dāng)前時(shí)間的簡(jiǎn)單實(shí)例,有需要的朋友可以參考一下2013-09-09Java構(gòu)造代碼塊,靜態(tài)代碼塊原理與用法實(shí)例分析
這篇文章主要介紹了Java構(gòu)造代碼塊,靜態(tài)代碼塊,結(jié)合實(shí)例形式分析了Java構(gòu)造代碼塊,靜態(tài)代碼塊的功能、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04使用spring連接及操作mongodb3.0實(shí)例
這篇文章主要介紹了使用spring連接及操作mongodb3.0實(shí)例,詳細(xì)的介紹了使用spring的情況下,在java中簡(jiǎn)單操作mongodb。有興趣的可以了解一下。2016-12-12java多線(xiàn)程實(shí)現(xiàn)服務(wù)器端與多客戶(hù)端之間的通信
本篇文章主要介紹了java多線(xiàn)程實(shí)現(xiàn)服務(wù)器端與多客戶(hù)端之間的通信,介紹了多線(xiàn)程來(lái)實(shí)現(xiàn)服務(wù)器與多線(xiàn)程之間的通信的基本步驟,有需要的小伙伴可以參考下。2016-10-10解決常見(jiàn)的Eclipse SVN插件報(bào)錯(cuò)方法詳解
本篇文章是對(duì)常見(jiàn)的Eclipse SVN插件報(bào)錯(cuò)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05谷歌二維碼引擎com.google.zxing二維碼生成與解析
這篇文章主要給大家介紹了關(guān)于谷歌二維碼引擎com.google.zxing二維碼生成與解析的相關(guān)資料,zxing是google開(kāi)源的二維碼生成和解析工具,需要的朋友可以參考下2023-07-07Spring Boot 數(shù)據(jù)校驗(yàn)@Valid+統(tǒng)一異常處理的實(shí)現(xiàn)
這篇文章主要介紹了Spring Boot 數(shù)據(jù)校驗(yàn)@Valid+統(tǒng)一異常處理的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-04-04詳解SpringBoot實(shí)現(xiàn)事件同步與異步監(jiān)聽(tīng)
這篇文章主要通過(guò)示例為大家詳細(xì)介紹了SpringBoot中的事件的用法和原理以及如何實(shí)現(xiàn)事件同步與異步監(jiān)聽(tīng),快跟隨小編一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06