" />

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

Java實(shí)現(xiàn)局域網(wǎng)聊天小程序

 更新時(shí)間:2022年05月19日 17:02:48   作者:NiuPlus  
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)局域網(wǎng)聊天小程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了Java實(shí)現(xiàn)局域網(wǎng)聊天的具體代碼,供大家參考,具體內(nèi)容如下

開(kāi)發(fā)環(huán)境:

IDEA 2018.2 集成開(kāi)發(fā)工具。

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

1、用戶上線,向服務(wù)器通知并注冊(cè)。

2、同局域網(wǎng)下,所有注冊(cè)用戶可以進(jìn)行群聊。

3、同局域網(wǎng)下,所有用戶可與任意已注冊(cè)用戶進(jìn)行私聊。

4、用戶下線,通知服務(wù)器,服務(wù)器更新信息。

實(shí)現(xiàn)原理:

1、服務(wù)器端實(shí)例化一個(gè)ServerSocket對(duì)象,調(diào)用accept方法等待客戶端連接到服務(wù)器。

2、客戶端實(shí)例化 Socket 對(duì)象,并使用構(gòu)造方法與服務(wù)器建立鏈接。

3、服務(wù)器端根據(jù)客戶端輸入信息,辨別客戶端請(qǐng)求的功能從而做出相應(yīng)響應(yīng)。

實(shí)用技術(shù):

為了能夠高效的處理客戶端的請(qǐng)求,在服務(wù)器端使用多線程處理客戶端請(qǐng)求。并且使用 ConcurrentHashMap 來(lái)存儲(chǔ)所有注冊(cè)過(guò)的客戶端。

項(xiàng)目源碼(解釋寫(xiě)在代碼的注釋當(dāng)中):

服務(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.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ManyThreadServer {
? ? //存儲(chǔ)所有注冊(cè)的客戶端
? ? private static Map<String, Socket> clientMap = new ConcurrentHashMap<String,Socket>();
? ? //具體的處理每個(gè)客戶端的請(qǐng)求
? ? private static class ExcuteClient implements Runnable{
? ? ? ? private Socket client;
? ? ? ? public ExcuteClient(Socket client) {
? ? ? ? ? ? this.client = client;
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void run() {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? //獲取客戶端的輸出流,讀取客戶端消息,并處理
? ? ? ? ? ? ? ? Scanner in = new Scanner(client.getInputStream());
? ? ? ? ? ? ? ? String strFromClient;
? ? ? ? ? ? ? ? while(true){
? ? ? ? ? ? ? ? ? ? if(in.hasNextLine()){
? ? ? ? ? ? ? ? ? ? ? ? strFromClient = in.nextLine();
? ? ? ? ? ? ? ? ? ? ? ? //在Windows下默認(rèn)換行是:\r\n,所以把\r要轉(zhuǎn)換為空字符串
? ? ? ? ? ? ? ? ? ? ? ? Pattern pattern = Pattern.compile("\r");
? ? ? ? ? ? ? ? ? ? ? ? Matcher matcher = pattern.matcher(strFromClient);
? ? ? ? ? ? ? ? ? ? ? ? strFromClient = matcher.replaceAll("");
? ? ? ? ? ? ? ? ? ? ? ? //注冊(cè)流程
? ? ? ? ? ? ? ? ? ? ? ? if(strFromClient.startsWith("useName")){
? ? ? ? ? ? ? ? ? ? ? ? ? ? String useName = strFromClient.split("\\:")[1];
? ? ? ? ? ? ? ? ? ? ? ? ? ? registerUser(useName,client);
? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? //群聊功能
? ? ? ? ? ? ? ? ? ? ? ? if(strFromClient.startsWith("G")){
? ? ? ? ? ? ? ? ? ? ? ? ? ? String msg = strFromClient.split("\\:")[1];
? ? ? ? ? ? ? ? ? ? ? ? ? ? groupChat(msg,client);
? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? //私聊功能
? ? ? ? ? ? ? ? ? ? ? ? if(strFromClient.startsWith("P")){
? ? ? ? ? ? ? ? ? ? ? ? ? ? String userName = strFromClient.split("\\:")[1].split("-")[0];
? ? ? ? ? ? ? ? ? ? ? ? ? ? String msg = strFromClient.split("\\:")[1].split("-")[1];
? ? ? ? ? ? ? ? ? ? ? ? ? ? privateChat(userName,msg,client);
? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? //用戶退出
? ? ? ? ? ? ? ? ? ? ? ? if(strFromClient.startsWith("B")){
? ? ? ? ? ? ? ? ? ? ? ? ? ? String userName = null;
? ? ? ? ? ? ? ? ? ? ? ? ? ? //根據(jù)Socket找到UserName
? ? ? ? ? ? ? ? ? ? ? ? ? ? for(String keyName : clientMap.keySet()){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(clientMap.get(keyName).equals(client)){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? userName = keyName;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? System.out.println("用戶" + userName + "下線了。。。");
? ? ? ? ? ? ? ? ? ? ? ? ? ? clientMap.remove(userName);
? ? ? ? ? ? ? ? ? ? ? ? ? ? System.out.println("當(dāng)前共有用戶" + clientMap.size() + "人");
? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? else{
? ? ? ? ? ? ? ? ? ? ? ? ? ? PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8");
? ? ? ? ? ? ? ? ? ? ? ? ? ? out.println("輸入錯(cuò)誤。。。");
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? private void registerUser(String name,Socket client){
? ? ? ? ? ? System.out.println("用戶:" + name + "已上線!");
? ? ? ? ? ? clientMap.put(name,client);
? ? ? ? ? ? System.out.println("當(dāng)前在線人數(shù):" + clientMap.size() + "人!");
? ? ? ? ? ? //既然是用戶在注冊(cè),所以這里服務(wù)器通知用戶注冊(cè)結(jié)果
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8");
? ? ? ? ? ? ? ? out.println("用戶注冊(cè)成功!");
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? private void groupChat(String msg,Socket client){
? ? ? ? ? ? //取出clientMap中所有的Entry對(duì)象,遍歷每個(gè)用戶,并且發(fā)送消息
? ? ? ? ? ? Set<Map.Entry<String,Socket>> clientSet = clientMap.entrySet();
? ? ? ? ? ? for(Map.Entry<String,Socket> entry:clientSet){
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? Socket socket = entry.getValue();
? ? ? ? ? ? ? ? ? ? //取得輸出流,向客戶端發(fā)送消息
? ? ? ? ? ? ? ? ? ? PrintStream out = new PrintStream(socket.getOutputStream(),true,"UTF-8");
? ? ? ? ? ? ? ? ? ? out.println("由端口號(hào)為"+ client.getPort() + "發(fā)來(lái)的群聊消息:" + msg);
? ? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? private void privateChat(String userName,String msg,Socket client){
? ? ? ? ? ? Socket privateSocket = clientMap.get(userName);
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? PrintStream out = new PrintStream(privateSocket.getOutputStream(),true,"UTF-8");
? ? ? ? ? ? ? ? out.println("由端口號(hào)為:" + client.getPort() + "發(fā)來(lái)的消息:" + msg);
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? public static void main(String[] args)throws Exception{
? ? ? ? //為了提高效率,這里使用多線程進(jìn)行處理
? ? ? ? ExecutorService executorService = Executors.newFixedThreadPool(30);
? ? ? ? //實(shí)例化ServerSocket對(duì)象,并指定IP為本地主機(jī),端口號(hào)為6666
? ? ? ? ServerSocket serverSocket = new ServerSocket(6666);
? ? ? ? for(int i = 0; i < 30;i++){
? ? ? ? ? ? System.out.println("等待用戶連接。。。");
? ? ? ? ? ? //等待客戶端連接服務(wù)器
? ? ? ? ? ? Socket client = serverSocket.accept();
? ? ? ? ? ? System.out.println("有客戶端連接,端口號(hào)為:" + client.getPort());
? ? ? ? ? ? //啟動(dòng)線程,并處理客戶端請(qǐng)求
? ? ? ? ? ? executorService.submit(new ExcuteClient(client));
? ? ? ? }
? ? ? ? //關(guān)閉線程,關(guān)閉服務(wù)器
? ? ? ? executorService.shutdown();
? ? ? ? serverSocket.close();
? ? }
}

客戶端:

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
?
/**
?* ?接收服務(wù)端發(fā)來(lái)的消息
?*/
class FromServer implements Runnable{
? ? Socket client;
? ? public FromServer(Socket client){
? ? ? ? this.client = client;
? ? }
? ? @Override
? ? public void run() {
? ? ? ? try {
? ? ? ? ? ? Scanner in = new Scanner(client.getInputStream());
? ? ? ? ? ? while (true) {
? ? ? ? ? ? ? ? if (in.hasNextLine()) {
? ? ? ? ? ? ? ? ? ? System.out.println("服務(wù)器:" + in.nextLine());
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? //判斷客戶端是否退出,如果推出,跳出循環(huán),并關(guān)閉流
? ? ? ? ? ? ? ? if (client.isClosed()) {
? ? ? ? ? ? ? ? ? ? System.out.println("客戶端關(guān)閉。。。");
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? in.close();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
}
?
/**
?* ?向服務(wù)端發(fā)出消息
?*/
class ToServer ?implements Runnable{
? ? Socket client;
? ? public ToServer(Socket client){
? ? ? ? this.client = client;
? ? }
? ? @Override
? ? public void run() {
? ? ? ? try {
? ? ? ? ? ? Scanner scanner = new Scanner(System.in);
? ? ? ? ? ? PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8");
? ? ? ? ? ? while (true) {
? ? ? ? ? ? ? ? System.out.println("請(qǐng)輸入信息:");
? ? ? ? ? ? ? ? String strToserver;
? ? ? ? ? ? ? ? if(scanner.hasNextLine()){
? ? ? ? ? ? ? ? ? ? strToserver = scanner.nextLine().trim();
? ? ? ? ? ? ? ? ? ? out.println(strToserver);
? ? ? ? ? ? ? ? ? ? //客戶端退出標(biāo)志:B
? ? ? ? ? ? ? ? ? ? if(strToserver.startsWith("B")){
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("客戶端退出。。。");
? ? ? ? ? ? ? ? ? ? ? ? scanner.close();
? ? ? ? ? ? ? ? ? ? ? ? out.close();
? ? ? ? ? ? ? ? ? ? ? ? client.close();
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
}
public class ManyThreadClient {
? ? public static void main(String[] args){
? ? ? ? try {
? ? ? ? ? ? //實(shí)例化Socket對(duì)象,與服務(wù)器建立連接
? ? ? ? ? ? Socket client = new Socket("127.0.0.1",6666);
? ? ? ? ? ? //為了發(fā)送消息和接收消息可以同時(shí)進(jìn)行,使用多線程進(jìn)行處理
? ? ? ? ? ? Thread thread1 = new Thread(new FromServer(client));
? ? ? ? ? ? Thread thread2 = new Thread(new ToServer(client));
? ? ? ? ? ? thread1.start();
? ? ? ? ? ? thread2.start();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
}

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

相關(guān)文章

  • HashSet底層竟然是HashMap實(shí)現(xiàn)問(wèn)題

    HashSet底層竟然是HashMap實(shí)現(xiàn)問(wèn)題

    這篇文章主要介紹了HashSet底層竟然是HashMap實(shí)現(xiàn)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • java代碼如何讀取bootstrap.yml配置信息

    java代碼如何讀取bootstrap.yml配置信息

    這篇文章主要介紹了java代碼如何讀取bootstrap.yml配置信息問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Spring security 如何開(kāi)放 Swagger 訪問(wèn)權(quán)限

    Spring security 如何開(kāi)放 Swagger 訪問(wèn)權(quán)限

    這篇文章主要介紹了Spring security 如何開(kāi)放 Swagger 訪問(wèn)權(quán)限操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • C# TreeNode案例詳解

    C# TreeNode案例詳解

    這篇文章主要介紹了C# TreeNode案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • JUC中的wait與notify方法實(shí)現(xiàn)原理詳解

    JUC中的wait與notify方法實(shí)現(xiàn)原理詳解

    這篇文章主要介紹了JUC中的wait與notify方法實(shí)現(xiàn)原理,在進(jìn)行wait()之前,就代表著需要爭(zhēng)奪Synchorized,而Synchronized代碼塊通過(guò)javap生成的字節(jié)碼中包含monitor?enter和monitor?exit兩個(gè)指令
    2023-03-03
  • POI通用導(dǎo)出Excel(.xls,.xlsx)的方法

    POI通用導(dǎo)出Excel(.xls,.xlsx)的方法

    這篇文章主要介紹了POI通用導(dǎo)出Excel(.xls,.xlsx)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Java解析json報(bào)文實(shí)例解析

    Java解析json報(bào)文實(shí)例解析

    這篇文章主要介紹了Java解析json報(bào)文實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java的作業(yè)調(diào)度類庫(kù)Quartz基本使用指南

    Java的作業(yè)調(diào)度類庫(kù)Quartz基本使用指南

    這篇文章主要介紹了Java的作業(yè)調(diào)度類庫(kù)Quartz基本使用指南,Quartz能夠讓類按照指定的計(jì)劃順序執(zhí)行,需要的朋友可以參考下
    2016-03-03
  • Java使用Lambda表達(dá)式查找list集合中是否包含某值問(wèn)題

    Java使用Lambda表達(dá)式查找list集合中是否包含某值問(wèn)題

    Java使用Lambda表達(dá)式查找list集合中是否包含某值的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • JPA多條件復(fù)雜SQL動(dòng)態(tài)分頁(yè)查詢功能

    JPA多條件復(fù)雜SQL動(dòng)態(tài)分頁(yè)查詢功能

    這篇文章主要介紹了JPA多條件復(fù)雜SQL動(dòng)態(tài)分頁(yè)查詢功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09

最新評(píng)論