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

Java SE實(shí)現(xiàn)多人聊天室功能

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

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

實(shí)現(xiàn)功能:

1.實(shí)現(xiàn)用戶注冊(cè)上線,下線

2.實(shí)現(xiàn)群聊和私聊功能

3.實(shí)現(xiàn)統(tǒng)計(jì)當(dāng)前在線人數(shù)

實(shí)現(xiàn)思路:

1.首先,要實(shí)現(xiàn)服務(wù)端與客戶端之間的連接

這里是使用套接字建立TCP連接:

(1)服務(wù)器端先實(shí)例化一個(gè)描述服務(wù)器端口號(hào)的ServerSocket對(duì)象

(2)客戶端要?jiǎng)?chuàng)建Socket對(duì)象來(lái)連接指定的服務(wù)器端

(3)服務(wù)器端調(diào)用ServerSocket類的accept()方法來(lái)監(jiān)聽連接到服務(wù)器端的客戶端信息

(4)若服務(wù)器端與客戶端連接成功,雙方將返回一個(gè)Socket對(duì)象,此時(shí)雙方可以進(jìn)行通信

(5)服務(wù)器端與客戶端使用I/O流進(jìn)行連接,服務(wù)端的輸出流連接客戶端的輸入流,客戶端的輸出流連接服務(wù)端的輸入流

(6)使用close()方法關(guān)閉套接字(一定要記得關(guān)閉)

2.因?yàn)槭菗碛幸粋€(gè)服務(wù)端來(lái)實(shí)現(xiàn)多個(gè)客戶端的連接,此處還要解決的是多線程的問題。

每個(gè)客戶端需要兩個(gè)線程,來(lái)分別處理向服務(wù)端發(fā)送消息和向服務(wù)端接收消息

而服務(wù)端,當(dāng)每增加一個(gè)客戶端與服務(wù)端連接,服務(wù)端都要多創(chuàng)建一個(gè)線程來(lái)處理與客戶端的連接

具體代碼:

單線程實(shí)現(xiàn):

客戶端

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
 
/**
 * @author LXY
 * @email 403824215@qq.com
 * @date 2018/7/20 15:46
 */
//客戶端
public class SingleClient {
 public static void main(String[] args) throws IOException {
  //客戶端連接服務(wù)器,返回套接字Socket對(duì)象
  Socket socket = new Socket("127.0.0.1",6666);
  //獲取服務(wù)端的輸出流,向服務(wù)器端輸出內(nèi)容
  PrintStream printStream = new PrintStream(socket.getOutputStream());
  printStream.println("我是客戶端" + socket.getLocalPort());
  //獲取服務(wù)器端的輸入流,讀取服務(wù)器端的內(nèi)容
  Scanner scanner = new Scanner(socket.getInputStream());
  scanner.useDelimiter("\n");
  if(scanner.hasNext())
  {
   System.out.println(scanner.next());
  }
  //關(guān)閉流
  socket.close();
 }
}

服務(wù)端

import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
 
/**
 * @author LXY
 * @email 403824215@qq.com
 * @date 2018/7/20 15:34
 */
//服務(wù)端
public class SingleServer {
 public static void main(String[] args) throws IOException {
  //創(chuàng)建服務(wù)器端的ServerSocket對(duì)象,等待客戶端進(jìn)行連接
  ServerSocket serverSocket = new ServerSocket(6666);
  System.out.println("服務(wù)器的端口號(hào)為6666,等待客戶端連接。。。");
  //偵聽并接收服務(wù)器端的連接,返回套接字Socket對(duì)象
  Socket socket = serverSocket.accept();
  //獲取客戶端的輸入流,讀取客戶端的輸入內(nèi)容
  Scanner scanner = new Scanner(socket.getInputStream());
  scanner.useDelimiter("\n");
  if(scanner.hasNext())
  {
   System.out.println("客戶端發(fā)來(lái)消息:" + scanner.next());
  }
  //獲取客戶端的輸出流,向客戶端輸出內(nèi)容
  PrintStream printStream = new PrintStream(socket.getOutputStream());
  printStream.println("客戶端你好,我是服務(wù)器端:" + serverSocket.getLocalPort());
  //關(guān)閉流
  serverSocket.close();
 }
}

多線程實(shí)現(xiàn)

客戶端

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
 
/**
 * @author LXY
 * @email 403824215@qq.com
 * @date 2018/7/20 15:55
 */
//客戶端
 
//客戶端讀取服務(wù)器端信息的線程
class ClientReadServer implements Runnable
{
 private Socket socket;
 
 public ClientReadServer(Socket socket)
 {
  this.socket = socket;
 }
 
 public void run() {
  try {
   Scanner scanner = new Scanner(socket.getInputStream());
   while (scanner.hasNext())
   {
    System.out.println(scanner.next());
   }
   socket.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}
 
 
//客戶端向服務(wù)端發(fā)送信息的線程
class ClientSendServer implements Runnable
{
 private Socket socket;
 
 public ClientSendServer(Socket socket)
 {
  this.socket = socket;
 }
 
 public void run() {
  try {
   PrintStream printStream = new PrintStream(socket.getOutputStream());
   Scanner scanner = new Scanner(System.in);
   while (true)
   {
    String msg = null;
    if(scanner.hasNext())
    {
     msg = scanner.next();
     printStream.println(msg);
    }
    if(msg.equals("bye"))
    {
     scanner.close();
     printStream.close();
     break;
    }
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 
 }
}
 
public class MultiClient {
 public static void main(String[] args) throws IOException {
  Socket socket = new Socket("127.0.0.1",6666);
  Thread read = new Thread(new ClientReadServer(socket));
  Thread send = new Thread(new ClientSendServer(socket));
  read.start();
  send.start();
 }
}

服務(wù)端

import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
/**
 * @author LXY
 * @email 403824215@qq.com
 * @date 2018/7/20 16:12
 */
class Server implements Runnable
{
 private static Map<String,Socket> map = new ConcurrentHashMap<String, Socket>();
 
 private Socket socket;
 
 public Server(Socket socket)
 {
  this.socket = socket;
 }
 
 public void run() {
  try {
   Scanner scanner = new Scanner(socket.getInputStream());
   String msg = null;
   while (true)
   {
    if(scanner.hasNextLine())
    {
     msg = scanner.nextLine();
     Pattern pattern = Pattern.compile("\r");
     Matcher matcher = pattern.matcher(msg);
     msg = matcher.replaceAll("");
     //用戶注冊(cè)——格式:userName:用戶名
     if(msg.startsWith("userName:"))
     {
      String userName = msg.split("\\:")[1];
      userRegist(userName,socket);
      continue;
     }
     //群聊——格式:G:群聊信息
     else if(msg.startsWith("G:"))
     {
      firstStep(socket);
      String str = msg.split("\\:")[1];
      groupChat(socket,str);
      continue;
     }
     else if(msg.startsWith("P:") && msg.contains("-"))
     {
      firstStep(socket);
      String userName = msg.split("\\:")[1].split("-")[0];
      String str = msg.split("\\:")[1].split("-")[1];
      privateChat(socket,userName,str);
      continue;
     }
     else if(msg.contains("bye"))
     {
      firstStep(socket);
      userExit(socket);
      continue;
     }
     else
     {
      PrintStream printStream = new PrintStream(socket.getOutputStream());
      printStream.println("格式輸入錯(cuò)誤");
      continue;
 
     }
    }
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 
 }
 
 private void firstStep(Socket socket) throws IOException {
  Set<Map.Entry<String,Socket>> set = map.entrySet();
  for(Map.Entry<String,Socket> entry:set)
  {
   if(entry.getValue().equals(socket))
   {
    if(entry.getValue() == null)
    {
     PrintStream printStream = new PrintStream(socket.getOutputStream());
     printStream.println("請(qǐng)先進(jìn)行注冊(cè)操作!格式為:[userName:用戶名]");
    }
   }
  }
 }
 
 private void userRegist(String userName, Socket socket) {
  map.put(userName,socket);
  System.out.println("用戶名:" + userName + "客戶端" + socket +"上線了?。?);
  System.out.println("當(dāng)前在線人數(shù)為" + map.size() + "人");
 }
 
 private void groupChat(Socket socket, String msg) throws IOException {
  Set<Map.Entry<String,Socket>> set = map.entrySet();
  String userName = null;
  for(Map.Entry<String,Socket> entry:set)
  {
   if(entry.getValue().equals(socket))
   {
    userName = entry.getKey();
    break;
   }
  }
  for(Map.Entry<String,Socket> entry:set)
  {
   Socket client = entry.getValue();
   PrintStream printStream = new PrintStream(client.getOutputStream());
   printStream.println(userName + "說(shuō)" + msg);
  }
 }
 
 private void privateChat(Socket socket, String userName, String msg) throws IOException {
  String curUser = null;
  Set<Map.Entry<String,Socket>> set = map.entrySet();
  for(Map.Entry<String,Socket> entry:set)
  {
   if(entry.getValue().equals(socket))
   {
    curUser = entry.getKey();
    break;
   }
  }
  Socket client = map.get(userName);
  PrintStream printStream = new PrintStream(client.getOutputStream());
  printStream.println(curUser + "私聊說(shuō)" + msg);
 }
 
 private void userExit(Socket socket) {
  String userName = null;
  for(String key:map.keySet())
  {
   if(map.get(key).equals(socket))
   {
    userName = key;
    break;
   }
  }
  map.remove(userName,socket);
  System.out.println("用戶" + userName + "已下線");
 }
}
 
 
public class MultiServer {
 public static void main(String[] args) {
  try {
   ServerSocket serverSocket = new ServerSocket(6666);
   //使用線程池
   ExecutorService executorService = Executors.newFixedThreadPool(20);
   for(int i = 0;i < 20;i++)
   {
    System.out.println("歡迎來(lái)到聊天室。。。");
    Socket socket = serverSocket.accept();
    System.out.println("新人加入。。。");
    executorService.execute(new Server(socket));
   }
   executorService.shutdown();
   serverSocket.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
 
 }
}

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

相關(guān)文章

  • Java IO文件編碼轉(zhuǎn)換實(shí)現(xiàn)代碼

    Java IO文件編碼轉(zhuǎn)換實(shí)現(xiàn)代碼

    這篇文章主要介紹了Java IO文件編碼轉(zhuǎn)換實(shí)現(xiàn)代碼,有需要的朋友可以參考一下
    2013-12-12
  • Java利用cors實(shí)現(xiàn)跨域請(qǐng)求實(shí)例

    Java利用cors實(shí)現(xiàn)跨域請(qǐng)求實(shí)例

    本篇文章主要介紹了Java利用cors實(shí)現(xiàn)跨域請(qǐng)求實(shí)例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2017-05-05
  • Java實(shí)現(xiàn)排列組合算法的兩種方案

    Java實(shí)現(xiàn)排列組合算法的兩種方案

    Java排列組合算法是一種用于生成所有可能的排列和組合的算法,在Java中,可以使用遞歸或迭代的方式實(shí)現(xiàn)排列組合算法,本文給大家介紹了Java實(shí)現(xiàn)排列組合算法的兩種方案,需要的朋友可以參考下
    2024-04-04
  • SpringBoot+Mybatis項(xiàng)目使用Redis做Mybatis的二級(jí)緩存的方法

    SpringBoot+Mybatis項(xiàng)目使用Redis做Mybatis的二級(jí)緩存的方法

    本篇文章主要介紹了SpringBoot+Mybatis項(xiàng)目使用Redis做Mybatis的二級(jí)緩存的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • 解決SpringBoot配置文件項(xiàng)目重啟出現(xiàn)亂碼的問題

    解決SpringBoot配置文件項(xiàng)目重啟出現(xiàn)亂碼的問題

    最近在創(chuàng)建了SpringBoot項(xiàng)目后往配置文件中寫了相關(guān)的系統(tǒng)配置,并且在上面加了中文注釋,但是在重啟項(xiàng)目或開機(jī)重啟后遇到了注釋亂碼的情況,下面這篇文章主要給大家介紹一下如何解決SpringBoot配置文件項(xiàng)目重啟出現(xiàn)亂碼的問題,需要的朋友可以參考下
    2023-06-06
  • java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(1)

    java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(1)

    下面小編就為大家?guī)?lái)一篇Java基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧,希望可以幫到你
    2021-07-07
  • 關(guān)于spring?boot使用?jdbc+mysql?連接的問題

    關(guān)于spring?boot使用?jdbc+mysql?連接的問題

    這篇文章主要介紹了spring?boot使用?jdbc+mysql?連接,在這里mysql?8.x版本驅(qū)動(dòng)包,要使用?com.mysql.cj.jdbc.Driver作為驅(qū)動(dòng)類,文中給大家詳細(xì)介紹,需要的朋友可以參考下
    2022-03-03
  • SpringBoot 如何添加容器啟動(dòng)的初始化邏輯的操作方法

    SpringBoot 如何添加容器啟動(dòng)的初始化邏輯的操作方法

    這篇文章主要介紹了SpringBoot 如何添加容器啟動(dòng)的初始化邏輯,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • 解決Maven項(xiàng)目加載spring bean的配置xml文件會(huì)提示找不到問題

    解決Maven項(xiàng)目加載spring bean的配置xml文件會(huì)提示找不到問題

    這篇文章主要介紹了解決Maven項(xiàng)目加載spring bean的配置xml文件會(huì)提示找不到問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java 深入探究講解工廠方法模式

    Java 深入探究講解工廠方法模式

    工廠方法模式(FACTORY METHOD)是一種常用的類創(chuàng)建型設(shè)計(jì)模式,此模式的核心精神是封裝類中變化的部分,提取其中個(gè)性化善變的部分為獨(dú)立類,通過依賴注入以達(dá)到解耦、復(fù)用和方便后期維護(hù)拓展的目的。它的核心結(jié)構(gòu)有四個(gè)角色,分別是抽象工廠、具體工廠、抽象產(chǎn)品、具體產(chǎn)品
    2022-04-04

最新評(píng)論