java實(shí)現(xiàn)多客戶(hù)聊天功能
java 實(shí)現(xiàn)多客戶(hù)端聊天(TCP),供大家參考,具體內(nèi)容如下
1. 編程思想:
1)、要想實(shí)現(xiàn)多客戶(hù)端聊天,首先需要有多個(gè)客戶(hù)端,而這些客戶(hù)端需要隨時(shí)發(fā)送消息和接受消息,所以收發(fā)消息需要放入不同的線(xiàn)程中。
2)、多客戶(hù)聊天并不是多個(gè)客戶(hù)之間進(jìn)行兩兩通信,而是需要所有客戶(hù)端與服務(wù)端進(jìn)行交互,再由服務(wù)端統(tǒng)一下發(fā)信息到其他參與聊天的客戶(hù)端。
2. 代碼實(shí)現(xiàn):
2.1 實(shí)現(xiàn)專(zhuān)用于接收消息的子線(xiàn)程ReceiveThread
將接收消息和發(fā)送消息分為兩個(gè)線(xiàn)程,其中將發(fā)送消息寫(xiě)入主線(xiàn)程中,開(kāi)啟新的線(xiàn)程用于接收消息。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; public class ReceiveThread extends Thread{ private Socket socket; //私有的成員變量,套接字 public ReceiveThread(Socket socket) { this.socket = socket; } @Override public void run() { BufferedReader br = null;//使用帶緩沖區(qū)的字符輸入流接收信息 try { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (IOException e) { e.printStackTrace(); } while(true){ try { System.out.println(br.readLine()); } catch (IOException e) { e.printStackTrace(); } } } }
2.2 客戶(hù)端代碼
import java.io.IOException; import java.io.PrintStream; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; public class Client { @SuppressWarnings("all") public static void main(String[] args) throws UnknownHostException, IOException { //ip:需要連接的服務(wù)端所在的ip //端口:客戶(hù)端連接的端口必須和服務(wù)端端口一致 Socket socket = new Socket("192.168.*.*",8080); Scanner scan = new Scanner(System.in); new ReceiveThread(socket).start(); //發(fā)送給服務(wù)端信息 while(true ){ PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println("一號(hào):"+scan.next()); } } }
注:
1)、客戶(hù)端代碼可以在局域網(wǎng)下的多臺(tái)電腦上運(yùn)行,只需要將ip地址改為服務(wù)端的ip,就能夠連接。
2)、如果想要使用同臺(tái)電腦完成一個(gè)服務(wù)端和兩個(gè)客戶(hù)端運(yùn)行,進(jìn)行測(cè)試多人聊天,可創(chuàng)建客戶(hù)端2,使用本機(jī)ip
Socket socket = new Socket("127.0.0.1",8080); Scanner scan = new Scanner(System.in); new ReceiveThread(socket).start(); //發(fā)送給服務(wù)端信息 while(true ){ PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println("二號(hào):"+scan.next()); }
2.3 服務(wù)端接收和轉(zhuǎn)發(fā)信息的線(xiàn)程ServerThread
服務(wù)端在每一個(gè)客戶(hù)端進(jìn)行連接時(shí),都會(huì)產(chǎn)生一個(gè)線(xiàn)程,用于服務(wù)這個(gè)客戶(hù),負(fù)責(zé)接收該客戶(hù)發(fā)送的信息,并轉(zhuǎn)發(fā)到參與多人聊天的其他客戶(hù)。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.InetAddress; import java.net.Socket; import java.util.Map.Entry; import java.util.Set; public class ServerThread extends Thread{ private Socket socket; public ServerThread(Socket socket) { this.socket = socket; } @Override public void run() { BufferedReader br = null; String str=null; try { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (IOException e) { e.printStackTrace(); } while(true){ try { str=br.readLine(); //在服務(wù)端輸出,可以監(jiān)測(cè)到所有人的聊天信息。 System.out.println(str); //發(fā)送到其他客戶(hù)端 Set<Entry<InetAddress, Socket>> entrySet = Server.map.entrySet(); for (Entry<InetAddress, Socket> entry : entrySet) { InetAddress key = entry.getKey(); Socket value = entry.getValue(); if(socket.getInetAddress()!=key){ PrintStream printStream = new PrintStream(value.getOutputStream()); printStream.println(str); } } } catch (IOException e) { e.printStackTrace(); } } } }
2.4 服務(wù)端代碼
import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ConcurrentHashMap; public class Server { @SuppressWarnings("all") public static ConcurrentHashMap<InetAddress, Socket> map =new ConcurrentHashMap<>(); public static void main(String[] args) throws IOException, InterruptedException { //創(chuàng)建服務(wù)端的ServerSocket ServerSocket server = new ServerSocket(8080); while(true){ //接收到客戶(hù)連接就創(chuàng)建一個(gè)對(duì)應(yīng)的套接字 Socket socket = server.accept(); //獲取該客戶(hù)的ip InetAddress inetAddress = socket.getInetAddress(); //將該客戶(hù)的ip和套接字裝入map集合 map.put(inetAddress, socket); //創(chuàng)建新的線(xiàn)程服務(wù)該客戶(hù) new ServerThread(socket).start(); } } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- java synchronized 鎖機(jī)制原理詳解
- Java實(shí)現(xiàn)遞歸計(jì)算n的階乘
- java多線(xiàn)程模擬實(shí)現(xiàn)售票功能
- Java CharacterEncodingFilter過(guò)濾器的理解和配置案例詳解
- Java面試題沖刺第二十六天--實(shí)戰(zhàn)編程2
- Java面試題沖刺第二十五天--并發(fā)編程3
- Java面試題沖刺第二十六天--實(shí)戰(zhàn)編程
- Java DatabaseMetaData用法案例詳解
- Java 動(dòng)態(tài)數(shù)組的實(shí)現(xiàn)示例
- Java中的equsals和==
相關(guān)文章
簡(jiǎn)單講解Java設(shè)計(jì)模式編程中的單一職責(zé)原則
這篇文章主要介紹了Java設(shè)計(jì)模式編程中的單一職責(zé)原則,這在團(tuán)隊(duì)開(kāi)發(fā)編寫(xiě)接口時(shí)經(jīng)常使用這樣的約定,需要的朋友可以參考下2016-02-02淺談java 面對(duì)對(duì)象(抽象 繼承 接口 多態(tài))
下面小編就為大家?guī)?lái)一篇淺談java 面對(duì)對(duì)象(抽象 繼承 接口 多態(tài))。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02SpringCloud如何使用Eureka實(shí)現(xiàn)服務(wù)之間的傳遞數(shù)據(jù)
這篇文章主要介紹了SpringCloud使用Eureka實(shí)現(xiàn)服務(wù)之間的傳遞數(shù)據(jù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Java中synchronized實(shí)現(xiàn)原理詳解
這篇文章主要介紹了Java中synchronized實(shí)現(xiàn)原理詳解,涉及synchronized實(shí)現(xiàn)同步的基礎(chǔ),Java對(duì)象頭,Monitor,Mark Word,鎖優(yōu)化,自旋鎖等相關(guān)內(nèi)容,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-11-11淺談Java高并發(fā)解決方案以及高負(fù)載優(yōu)化方法
這篇文章主要介紹了淺談Java高并發(fā)解決方案以及高負(fù)載優(yōu)化方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08