欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java通過Socket實(shí)現(xiàn)簡單多人聊天室

 更新時(shí)間:2021年04月07日 14:05:48   作者:haki  
這篇文章主要為大家詳細(xì)介紹了Java通過Socket實(shí)現(xiàn)簡單多人聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了Java通過Socket實(shí)現(xiàn)多人聊天室的具體代碼,供大家參考,具體內(nèi)容如下

Socket可以實(shí)現(xiàn)網(wǎng)絡(luò)上兩個(gè)程序通過雙向通道進(jìn)行數(shù)據(jù)的交換,此外它是Java中網(wǎng)絡(luò)TCP/IP協(xié)議的封裝,例如可以進(jìn)行網(wǎng)絡(luò)通信等等,下面我們就來簡單寫一下多人聊天室。

首先來分析一下要實(shí)現(xiàn)的流程

  • 首先建立一個(gè)服務(wù)器端,構(gòu)建ServerSocket并綁定端口
  • 創(chuàng)建socket客戶端,連接到指定ip以及其端口
  • 然后使用accept阻塞接收socket發(fā)出的連接請求
  • 獲取連接后的socket客戶端的輸入流和輸出流
  • 根據(jù)輸入流和輸出流進(jìn)行兩者數(shù)據(jù)的通信

值得一提是:該Socket是同步阻塞的,因此在socket客戶端需要進(jìn)行創(chuàng)建一個(gè)線程,來分別進(jìn)行向服務(wù)器輸出,和接收服務(wù)器傳輸?shù)臄?shù)據(jù)。要解決同步阻塞這個(gè)問題可以去了解JAVA NIO。

Socket客戶端代碼如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
 
public class Client{
 
 public static void main(String[] args) throws IOException {
 //創(chuàng)建連接指定Ip和端口的socket
 Socket socket = new Socket("127.0.0.1",5200);
 //獲取系統(tǒng)標(biāo)準(zhǔn)輸入流
 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
 PrintWriter out = new PrintWriter(socket.getOutputStream());
 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 //創(chuàng)建一個(gè)線程用于讀取服務(wù)器的信息
 new Thread(new Runnable() {
  @Override
  public void run() {
  try {
   while (true){
   System.out.println(in.readLine());
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
  }
 }).start();
 //寫信息給客戶端
 String line = reader.readLine();
 while (!"end".equalsIgnoreCase(line)){
  //將從鍵盤獲取的信息給到服務(wù)器
  out.println(line);
  out.flush();
  //顯示輸入的信息
  line = reader.readLine();
 }
 out.close();
 in.close();
 socket.close();
 
 }
}

由于要接收多個(gè)客戶端的請求,因此服務(wù)端需要多個(gè)線程進(jìn)行分別來接收客戶端的請求。

Socket服務(wù)端代碼如下:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.Vector;
 
public class Servers {
 //將接收到的socket變成一個(gè)集合
 protected static List<Socket> sockets = new Vector<>();
 
 public static void main(String[] args) throws IOException {
 //創(chuàng)建服務(wù)端
 ServerSocket server = new ServerSocket(5200);
 boolean flag = true;
 //接受客戶端請求
 while (flag){
  try {
  //阻塞等待客戶端的連接
  Socket accept = server.accept();
  synchronized (sockets){
  sockets.add(accept);
  }
  //多個(gè)服務(wù)器線程進(jìn)行對客戶端的響應(yīng)
  Thread thread = new Thread(new ServerThead(accept));
  thread.start();
  //捕獲異常。
  }catch (Exception e){
  flag = false;
  e.printStackTrace();
  }
 }
 //關(guān)閉服務(wù)器
 server.close();
 }
 
}

Server線程代碼如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
 
/**
 * 服務(wù)器線程,主要來處理多個(gè)客戶端的請求
 */
public class ServerThead extends Servers implements Runnable{
 
 Socket socket;
 String socketName;
 
 public ServerThead(Socket socket){
 this.socket = socket;
 }
 @Override
 public void run() {
 try {
  BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  //設(shè)置該客戶端的端點(diǎn)地址
  socketName = socket.getRemoteSocketAddress().toString();
  System.out.println("Client@"+socketName+"已加入聊天");
  print("Client@"+socketName+"已加入聊天");
  boolean flag = true;
  while (flag)
  {
  //阻塞,等待該客戶端的輸出流
  String line = reader.readLine();
  //若客戶端退出,則退出連接。
  if (line == null){
   flag = false;
   continue;
  }
  String msg = "Client@"+socketName+":"+line;
  System.out.println(msg);
  //向在線客戶端輸出信息
  print(msg);
  }
 
  closeConnect();
 } catch (IOException e) {
  try {
  closeConnect();
  } catch (IOException e1) {
  e1.printStackTrace();
  }
 }
 }
 /**
 * 向所有在線客戶端socket轉(zhuǎn)發(fā)消息
 * @param msg
 * @throws IOException
 */
 private void print(String msg) throws IOException {
 PrintWriter out = null;
 synchronized (sockets){
 for (Socket sc : sockets){
  out = new PrintWriter(sc.getOutputStream());
  out.println(msg);
  out.flush();
 }
 }
 }
 /**
 * 關(guān)閉該socket的連接
 * @throws IOException
 */
 public void closeConnect() throws IOException {
 System.out.println("Client@"+socketName+"已退出聊天");
 print("Client@"+socketName+"已退出聊天");
 //移除沒連接上的客戶端
 synchronized (sockets){
  sockets.remove(socket);
 }
 socket.close();
 }
}

由于要接收多個(gè)客戶端的信息,并轉(zhuǎn)發(fā)到每一個(gè)已經(jīng)連接上的客戶端,因此創(chuàng)建了一個(gè)Vector集合來保存每一個(gè)客戶端Socket,由于是多個(gè)線程同時(shí)對這個(gè)Vector集合進(jìn)行操作,因此加上synchronized關(guān)鍵字保證同步安全。

先運(yùn)行服務(wù)器端,然后在運(yùn)行多個(gè)客戶端就可以進(jìn)行多人聊天了。

下面是運(yùn)行的結(jié)果。

 

客戶端2

 

客戶端1

 

客戶端3

服務(wù)端

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java Spring詳解如何配置數(shù)據(jù)源注解開發(fā)以及整合Junit

    Java Spring詳解如何配置數(shù)據(jù)源注解開發(fā)以及整合Junit

    Spring 是目前主流的 Java Web 開發(fā)框架,是 Java 世界最為成功的框架。該框架是一個(gè)輕量級的開源框架,具有很高的凝聚力和吸引力,本篇文章帶你了解如何配置數(shù)據(jù)源、注解開發(fā)以及整合Junit
    2021-10-10
  • 關(guān)于Spring中聲明式事務(wù)的使用詳解

    關(guān)于Spring中聲明式事務(wù)的使用詳解

    Spring中事務(wù)分為編程式事務(wù)和聲明式事務(wù),編程式事務(wù)由于需要在代碼中硬編碼,在實(shí)際項(xiàng)目開發(fā)中比較少用到,實(shí)際開發(fā)中用的比較多的就是聲明式事務(wù),這篇文章主要給大家介紹了關(guān)于Spring中聲明式事務(wù)使用的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • 詳解Java中CountDownLatch異步轉(zhuǎn)同步工具類

    詳解Java中CountDownLatch異步轉(zhuǎn)同步工具類

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著CountDownLatch異步轉(zhuǎn)同步工具類展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • java 優(yōu)雅關(guān)閉線程池的方案

    java 優(yōu)雅關(guān)閉線程池的方案

    這篇文章主要介紹了java 優(yōu)雅關(guān)閉線程池的方案,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下
    2020-11-11
  • myBatis組件教程之緩存的實(shí)現(xiàn)與使用

    myBatis組件教程之緩存的實(shí)現(xiàn)與使用

    這篇文章主要給大家介紹了關(guān)于myBatis組件教程之緩存的實(shí)現(xiàn)與使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • RocketMQ實(shí)現(xiàn)消息分發(fā)的步驟

    RocketMQ實(shí)現(xiàn)消息分發(fā)的步驟

    RocketMQ 實(shí)現(xiàn)消息分發(fā)的核心機(jī)制是通過 Topic、Queue 和 Consumer Group 的配合實(shí)現(xiàn)的,下面給大家介紹RocketMQ實(shí)現(xiàn)消息分發(fā)的步驟,感興趣的朋友一起看看吧
    2024-03-03
  • 如何通過XML方式配置AOP過程解析

    如何通過XML方式配置AOP過程解析

    這篇文章主要介紹了如何通過XML方式配置AOP過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 基于list stream: reduce的使用實(shí)例

    基于list stream: reduce的使用實(shí)例

    這篇文章主要介紹了list stream: reduce的使用實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 在Spring Boot框架中使用AOP的正確姿勢

    在Spring Boot框架中使用AOP的正確姿勢

    aop是spring的兩大功能模塊之一,功能非常強(qiáng)大,為解耦提供了非常優(yōu)秀的解決方案。下面這篇文章主要給大家介紹了如何在Spring Boot框架中使用AOP的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-08-08
  • Mybatis批量修改的操作代碼

    Mybatis批量修改的操作代碼

    這篇文章主要介紹了Mybatis批量修改的操作代碼,包括整體批量修改的詳細(xì)代碼,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2017-09-09

最新評論