-
實(shí)現(xiàn)目標(biāo)
- 實(shí)現(xiàn)服務(wù)端與客戶端的連接
- 實(shí)現(xiàn)多個(gè)客戶端向服務(wù)端發(fā)送消息森缠,并由服務(wù)端將消息發(fā)送給每個(gè)客戶端
-
涉及的Java類
- java.net.ServerSocket 用于創(chuàng)建服務(wù)器端口
- java.net.Socket 用于創(chuàng)建Socket
- java.net.URLDecoder 用于在服務(wù)端將客戶端傳來(lái)的消息解碼
- java.util.ArrayList 用于動(dòng)態(tài)存放多個(gè)不同的Socket
- Java.util.scanner 用于從控制臺(tái)讀取輸入
-
具體實(shí)現(xiàn)思路
-
服務(wù)端
-
在主函數(shù)中建立一個(gè)端口用于監(jiān)聽(tīng)客戶端請(qǐng)求适刀,端口大小可自行設(shè)置
ServerSocket sock = new ServerSocket(1999)
-
需要接受多個(gè)客戶端的消息祷舀,因此需要和每個(gè)客戶端建立唯一的Socket對(duì)用于通信党涕,所以需要將新建的Socket存入動(dòng)態(tài)容器ArrayList<Socket>中
ArrayList<Socket> list = new ArrayList<Socket>()
-
使用while循環(huán),在while循環(huán)中調(diào)用ServerSocket的accept()方法等待客戶端請(qǐng)求返奉,當(dāng)接受到請(qǐng)求時(shí)就將返回的Socket存入容器中尤蒿,并新建一個(gè)線程(調(diào)用start函數(shù))
while(true) { Socket socket = sock.accept(); list.add(socket); new MsgThread(socket, list).start(); }
在線程類中進(jìn)行數(shù)據(jù)的讀入和輸出
定義類的屬性:Socket, ArrayList<Socket>,BufferedReader
-
定義構(gòu)造函數(shù)粗合,將傳入的參數(shù)賦給當(dāng)前對(duì)象的屬性,同時(shí)乌昔,通過(guò)Socket讀取客戶端的數(shù)據(jù)到BufferedReader對(duì)象
BufferedReader bf = new BufferedReader(new InputStreamReader(client.getInputStream)); //這里需要用InputStreamReader類來(lái)包裝client.getInputStream是為了將字節(jié)流轉(zhuǎn)換成字符流
-
重載run函數(shù)隙疚,將讀取的消息發(fā)送給除當(dāng)前socket對(duì)象外的其他客戶端
- 在這一步中的PrintWriter的使用要注意,一定要將自動(dòng)刷新設(shè)置為true磕道,否則消息就不能夠即時(shí)傳入到內(nèi)存中供屉,而是會(huì)等到程序結(jié)束時(shí)才傳入,這個(gè)bug卡了我好久
將消息解碼后顯示在控制臺(tái)上
-
-
客戶端
和服務(wù)端差不多的思路溺蕉,主要是實(shí)現(xiàn)消息的讀取和上傳
-
新建Socket伶丐,連接服務(wù)端
Socket client = new Socket("127.000.001", 1999;
讀取Socket中的數(shù)據(jù)并顯示在控制臺(tái)上
線程函數(shù)和服務(wù)端類似,無(wú)非是從控制臺(tái)讀取數(shù)據(jù)然后用getOutPutStream寫(xiě)入Socket中
-
-
源碼
//服務(wù)端 import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class ChatServer { //SockerList用于保存當(dāng)前連接的用戶 public static ArrayList<Socket> SocketList = new ArrayList<Socket>(); public static void main(String[] args) throws IOException { //創(chuàng)建端口監(jiān)聽(tīng)用戶的請(qǐng)求 ServerSocket sock = new ServerSocket(1999); System.out.println("服務(wù)啟動(dòng)...."); //服務(wù)器循環(huán)接受來(lái)自用戶端的請(qǐng)求 while(true) { //等待客戶端的請(qǐng)求疯特,捕獲到請(qǐng)求后返會(huì)一個(gè)Socket Socket socket = sock.accept(); System.out.println("服務(wù)連接...."); //將返回的Socket加入在線用戶列表中 SocketList.add(socket); System.out.println("當(dāng)前有" + (SocketList.size()) + "個(gè)用戶"); //創(chuàng)建一個(gè)新的線程哗魂,每個(gè)連接都會(huì)有自己獨(dú)立的任務(wù)線程,用于實(shí)現(xiàn)接受和發(fā)送消息 new MsgThread(socket, SocketList).start(); } } } //任務(wù)線程 class MsgThread extends Thread { //定義單個(gè)用戶連接的Socket Socket client; //定義用戶組的Socket ArrayList<Socket> clients; //定義讀入的數(shù)據(jù) BufferedReader br; //構(gòu)造函數(shù) public MsgThread(Socket client, ArrayList<Socket> clients) throws IOException { //調(diào)用父類的構(gòu)造函數(shù) super(); //使用傳入的參數(shù)初始化 this.client = client; this.clients = clients; //將當(dāng)前用戶的輸入緩存 br = new BufferedReader(new InputStreamReader(this.client.getInputStream())); } //重載run()函數(shù)漓雅,將接受到的用戶信息發(fā)送給其他用戶 @Override public void run() { try { String content = null; while(true) { //從某個(gè)客戶端獲取信息 if ((content = br.readLine()) != null) { //將消息發(fā)送給其他各個(gè)客戶端 for (Socket socket:clients) { //去掉自身客戶端 if (socket != client) { //將消息寫(xiě)入socket的緩存區(qū),設(shè)置為自動(dòng)刷新 PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); pw.println(content); } } content = URLDecoder.decode(content, "UTF-8"); System.out.println(content); } } } catch (IOException e) { e.printStackTrace(); } } }
//客戶端 import java.io.*; import java.net.*; public class ChatClient { public static void main(String[] args) throws Exception { //連接服務(wù)端 Socket client = new Socket("127.0.0.1", 1999); System.out.println("服務(wù)器已連接"); //新建線程 new MsgThread(client).start(); //獲取輸入 InputStream in = client.getInputStream(); BufferedReader bf = new BufferedReader(new InputStreamReader(in)); while (true) { String msg = bf.readLine(); //對(duì)收到的信息進(jìn)行解碼 msg=URLDecoder.decode(msg, "UTF-8"); System.out.println(msg); } } } class MsgThread extends Thread { Socket client; String hostname; public MsgThread(Socket client) { super(); this.client = client; try { //獲取本計(jì)算機(jī)名稱 InetAddress addr = InetAddress.getLocalHost(); hostname =addr.getHostName().toString(); } catch (UnknownHostException e1) { e1.printStackTrace(); } } //發(fā)送消息 @Override public void run() { try { //讀取控制臺(tái)輸入 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //將客戶端輸出流存到pw中 PrintWriter pw = new PrintWriter(client.getOutputStream(),true); while (true) { String msg = br.readLine(); //對(duì)發(fā)出的消息進(jìn)行編碼 msg = URLEncoder.encode(hostname + "說(shuō):"+ msg, "UTF-8"); pw.println(msg); } } catch (IOException e) { e.printStackTrace(); } } }
基于socket的進(jìn)程通信
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門(mén)峻呕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人趣效,你說(shuō)我怎么就攤上這事瘦癌。” “怎么了跷敬?”我有些...
- 文/不壞的土叔 我叫張陵讯私,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我西傀,道長(zhǎng)斤寇,這世上最難降的妖魔是什么? 我笑而不...
- 正文 為了忘掉前任拥褂,我火速辦了婚禮娘锁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘饺鹃。我一直安慰自己莫秆,他們只是感情好间雀,可當(dāng)我...
- 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著镊屎,像睡著了一般惹挟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缝驳,一...
- 那天连锯,我揣著相機(jī)與錄音,去河邊找鬼用狱。 笑死运怖,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的齿拂。 我是一名探鬼主播驳规,決...
- 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼署海!你這毒婦竟也來(lái)了吗购?” 一聲冷哼從身側(cè)響起,我...
- 序言:老撾萬(wàn)榮一對(duì)情侶失蹤砸狞,失蹤者是張志新(化名)和其女友劉穎捻勉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體刀森,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡踱启,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了研底。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片埠偿。...
- 正文 年R本政府宣布抖剿,位于F島的核電站,受9級(jí)特大地震影響识窿,放射性物質(zhì)發(fā)生泄漏斩郎。R本人自食惡果不足惜,卻給世界環(huán)境...
- 文/蒙蒙 一喻频、第九天 我趴在偏房一處隱蔽的房頂上張望缩宜。 院中可真熱鬧,春花似錦甥温、人聲如沸脓恕。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)炼幔。三九已至,卻和暖如春史简,著一層夾襖步出監(jiān)牢的瞬間乃秀,已是汗流浹背。 一陣腳步聲響...
- 正文 我出身青樓殉农,卻偏偏與公主長(zhǎng)得像刀脏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子超凳,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- 前言 兩個(gè)進(jìn)程如果要進(jìn)行通訊最基本的一個(gè)前提就是能夠唯一的標(biāo)識(shí)一個(gè)進(jìn)程愈污,在本地進(jìn)程通訊中我們可以使用 PID...
- JAVA面試題 1、作用域public,private,protected,以及不寫(xiě)時(shí)的區(qū)別答:區(qū)別如下:作用域 ...
- 小編費(fèi)力收集:給你想要的面試集合 1.C++或Java中的異常處理機(jī)制的簡(jiǎn)單原理和應(yīng)用轮傍。 當(dāng)JAVA程序違反了JA...
- Java是一種可以撰寫(xiě)跨平臺(tái)應(yīng)用軟件的面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言暂雹。Java 技術(shù)具有卓越的通用性、高效性创夜、平臺(tái)移植性和...