Java?Socket實(shí)現(xiàn)聊天室功能
本文實(shí)例為大家分享了Java Socket實(shí)現(xiàn)聊天室的具體代碼,供大家參考,具體內(nèi)容如下
1 創(chuàng)建登錄判斷類UserLogin
import java.util.HashSet; import java.util.Set; public class UserLogin { ? ? public static boolean login(String username) { ? ? ? ? Set<String> set = initUser(); ? ? ? ? // set中含有該username則登錄成功 ? ? ? ? return set.contains(username); ? ? } ? ? public static Set<String> initUser() { ? ? ? ? Set<String> set = new HashSet<>(); ? ? ? ? set.add("111"); ? ? ? ? set.add("222"); ? ? ? ? set.add("333"); ? ? ? ? set.add("444"); ? ? ? ? set.add("555"); ? ? ? ? return set; ? ? } }
2 創(chuàng)建登錄服務(wù)器LoginServer
import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class LoginServer { ? ? public static void main(String[] args) { ? ? ? ? int port = 6666; ? ? ? ? try (ServerSocket serverSocket = new ServerSocket(port)) { ? ? ? ? ? ? System.out.println("登錄服務(wù)器已經(jīng)啟動(dòng)"); ? ? ? ? ? ? while (true) { ? ? ? ? ? ? ? ? Socket socket = serverSocket.accept(); ? ? ? ? ? ? ? ? // 接收Client輸出的信息(username) ? ? ? ? ? ? ? ? InputStream inputStream = socket.getInputStream(); ? ? ? ? ? ? ? ? BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); ? ? ? ? ? ? ? ? String username = bufferedReader.readLine(); ? ? ? ? ? ? ? ? // 調(diào)用登錄方法,判斷是否成功登錄 ? ? ? ? ? ? ? ? OutputStream outputStream = socket.getOutputStream(); ? ? ? ? ? ? ? ? PrintStream printStream = new PrintStream(outputStream); ? ? ? ? ? ? ? ? if (UserLogin.login(username)) { ? ? ? ? ? ? ? ? ? ? System.out.println(username + "登錄成功"); ? ? ? ? ? ? ? ? ? ? // 登錄成功輸出"true"到Client ? ? ? ? ? ? ? ? ? ? printStream.println("true"); ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? System.out.println(username + "登錄失敗"); ? ? ? ? ? ? ? ? ? ? // 登錄失敗則輸出"false"到Client ? ? ? ? ? ? ? ? ? ? printStream.println("false"); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? printStream.flush(); ? ? ? ? ? ? } ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? } }
3 創(chuàng)建聊天服務(wù)器ChatServer
import com.socket.socketChatroom.bio.thread.ChatThread; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Map; public class ChatServer { ? ? // 保存當(dāng)前聊天中的所有Map<username,Socket> ? ? public static Map<String, Socket> socketMap = new HashMap<>(); ? ? public static void main(String[] args) { ? ? ? ? int port = 9999; ? ? ? ? try (ServerSocket serverSocket = new ServerSocket(port)) { ? ? ? ? ? ? System.out.println("聊天服務(wù)器已經(jīng)啟動(dòng)"); ? ? ? ? ? ? while (true) { ? ? ? ? ? ? ? ? Socket socket = serverSocket.accept(); ? ? ? ? ? ? ? ? // 接收Client輸出的username ? ? ? ? ? ? ? ? InputStream inputStream = socket.getInputStream(); ? ? ? ? ? ? ? ? BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); ? ? ? ? ? ? ? ? String username = bufferedReader.readLine(); ? ? ? ? ? ? ? ? System.out.println(username + "連接到聊天服務(wù)器"); ? ? ? ? ? ? ? ? // 連接聊天服務(wù)器成功則將它的<username,Socket>放入socketMap中 ? ? ? ? ? ? ? ? socketMap.put(username, socket); ? ? ? ? ? ? ? ? System.out.println(socketMap); ? ? ? ? ? ? ? ? // 因?yàn)榭赡苡卸鄠€(gè)Client與ChatServer進(jìn)行交互,所以一旦有Client連接成功就新創(chuàng)建一個(gè)線程與之交互 ? ? ? ? ? ? ? ? new ChatThread(username,socket).start(); ? ? ? ? ? ? } ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? throw new RuntimeException(e); ? ? ? ? } ? ? } }
4 創(chuàng)建客戶端Client
import com.socket.socketChatroom.bio.thread.ReadThread; import com.socket.socketChatroom.bio.thread.WriteThread; import java.io.*; import java.net.Socket; import java.util.Scanner; public class Client { ? ? public static void main(String[] args) { ? ? ? ? // 服務(wù)端地址,端口號 ? ? ? ? String ip = "127.0.0.1";// 本機(jī)IP地址 ? ? ? ? int port = 6666; // 必須和LoginServer的端口一樣 ? ? ? ? try { ? ? ? ? ? ? Socket client = new Socket(ip, port); ? ? ? ? ? ? Scanner scanner = new Scanner(System.in); ? ? ? ? ? ? System.out.println("請輸入用戶名"); ? ? ? ? ? ? String username = scanner.nextLine(); ? ? ? ? ? ? // 將用戶名輸出到LoginServer ? ? ? ? ? ? OutputStream outputStream = client.getOutputStream(); ? ? ? ? ? ? PrintStream printStream = new PrintStream(outputStream); ? ? ? ? ? ? printStream.println(username); ? ? ? ? ? ? printStream.flush(); ? ? ? ? ? ? // 接收LoginServer輸出的是否登錄成功標(biāo)志("true"或"false") ? ? ? ? ? ? InputStream inputStream = client.getInputStream(); ? ? ? ? ? ? BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); ? ? ? ? ? ? String state = bufferedReader.readLine(); ? ? ? ? ? ? // 如果為"true",則為登錄成功,可以開始聊天 ? ? ? ? ? ? if (Boolean.parseBoolean(state)) { ? ? ? ? ? ? ? ? chat(username); ? ? ? ? ? ? } ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? } ? ? public static void chat(String username) { ? ? ? ? try { ? ? ? ? ? ? String ip = "127.0.0.1";// 本機(jī)IP地址 ? ? ? ? ? ? int port = 9999;// 必須和ChatServer的端口一樣 ? ? ? ? ? ? // 連接聊天服務(wù)器ChatServer ? ? ? ? ? ? Socket socket = new Socket(ip, port); ? ? ? ? ? ? // 將username輸出到ChatServer ? ? ? ? ? ? OutputStream outputStream = socket.getOutputStream(); ? ? ? ? ? ? PrintStream printStream = new PrintStream(outputStream); ? ? ? ? ? ? printStream.println(username); ? ? ? ? ? ? printStream.flush(); ? ? ? ? ? ? // 因?yàn)榱奶斓氖瞻l(fā)消息不一定是與同一個(gè)人,所以創(chuàng)建兩個(gè)線程分別用于收和發(fā) ? ? ? ? ? ? new ReadThread(socket).start(); ? ? ? ? ? ? new WriteThread(socket).start(); ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? throw new RuntimeException(e); ? ? ? ? } ? ? } }
5 創(chuàng)建服務(wù)器用于處理聊天的線程類ChatThread
import com.socket.socketChatroom.bio.server.ChatServer; import java.io.*; import java.net.Socket; import java.util.HashSet; import java.util.Map; import java.util.Set; public class ChatThread extends Thread { ? ? private final String username; ? ? private final Socket socket; ? ? public ChatThread(String username, Socket socket) { ? ? ? ? this.username = username; ? ? ? ? this.socket = socket; ? ? } ? ? @Override ? ? public void run() { ? ? ? ? while (true) { ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? // 接收Client的WriteThread線程輸出的消息 ? ? ? ? ? ? ? ? InputStream inputStream = socket.getInputStream(); ? ? ? ? ? ? ? ? BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); ? ? ? ? ? ? ? ? String message = bufferedReader.readLine(); ? ? ? ? ? ? ? ? System.out.println(username + "說: " + message); ? ? ? ? ? ? ? ? // 將當(dāng)前所有在線的Client的username存入usernameSet中 ? ? ? ? ? ? ? ? Map<String, Socket> socketMap = ChatServer.socketMap; ? ? ? ? ? ? ? ? Set<String> usernameSet = new HashSet<>(); ? ? ? ? ? ? ? ? for (Map.Entry<String, Socket> map : socketMap.entrySet()) { ? ? ? ? ? ? ? ? ? ? usernameSet.add(map.getKey()); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? // 以"-"作為標(biāo)識符,判斷是群聊還是單聊 ? ? ? ? ? ? ? ? String[] values = message.split("-"); ? ? ? ? ? ? ? ? if (values.length == 2 && usernameSet.contains(values[0])) { //單聊 ? ? ? ? ? ? ? ? ? ? // values[0]為要指定發(fā)送的Client的username ? ? ? ? ? ? ? ? ? ? OutputStream outputStream = socketMap.get(values[0]).getOutputStream(); ? ? ? ? ? ? ? ? ? ? PrintStream printStream = new PrintStream(outputStream); ? ? ? ? ? ? ? ? ? ? // values[1]為消息內(nèi)容 ? ? ? ? ? ? ? ? ? ? printStream.println(username + "說: " + values[1]); ? ? ? ? ? ? ? ? ? ? printStream.flush(); ? ? ? ? ? ? ? ? } else {//群聊 ? ? ? ? ? ? ? ? ? ? // 將消息發(fā)送到除自己之外的所有Client ? ? ? ? ? ? ? ? ? ? for (String username : usernameSet) { ? ? ? ? ? ? ? ? ? ? ? ? if (socket != socketMap.get(username)) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? OutputStream outputStream = socketMap.get(username).getOutputStream(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? PrintStream printStream = new PrintStream(outputStream); ? ? ? ? ? ? ? ? ? ? ? ? ? ? printStream.println(this.username + "說: " + message); ? ? ? ? ? ? ? ? ? ? ? ? ? ? printStream.flush(); ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? ? ? throw new RuntimeException(e); ? ? ? ? ? ? } ? ? ? ? } ? ? } }
6 創(chuàng)建客戶端Client用于發(fā)送消息的線程類WriteThread
import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; public class WriteThread extends Thread { ? ? private final Socket socket; ? ? public WriteThread(Socket socket) { ? ? ? ? this.socket = socket; ? ? } ? ? @Override ? ? public void run() { ? ? ? ? while (true) { ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? // 獲取輸出流 ? ? ? ? ? ? ? ? OutputStream outputStream = socket.getOutputStream(); ? ? ? ? ? ? ? ? PrintStream printStream = new PrintStream(outputStream); ? ? ? ? ? ? ? ? // 鍵盤輸入要發(fā)送的消息,若為單聊,則以要發(fā)送的Client的username+"-",開頭,比如"111-hello",表示向111這個(gè)Client發(fā)送"hello" ? ? ? ? ? ? ? ? Scanner scanner = new Scanner(System.in); ? ? ? ? ? ? ? ? System.out.println("請輸入聊天內(nèi)容: "); ? ? ? ? ? ? ? ? String message = scanner.nextLine(); ? ? ? ? ? ? ? ? // 輸出消息到ChatServer ? ? ? ? ? ? ? ? printStream.println(message); ? ? ? ? ? ? ? ? printStream.flush(); ? ? ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? ? ? throw new RuntimeException(e); ? ? ? ? ? ? } ? ? ? ? } ? ? } }
7 創(chuàng)建客戶端Client用于接收消息的線程類ReadThread
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.Socket; public class ReadThread extends Thread { ? ? private final Socket socket; ? ? public ReadThread(Socket socket) { ? ? ? ? this.socket = socket; ? ? } ? ? @Override ? ? public void run() { ? ? ? ? while (true) { ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? // 從ChatServer獲取消息 ? ? ? ? ? ? ? ? InputStream inputStream = socket.getInputStream(); ? ? ? ? ? ? ? ? BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); ? ? ? ? ? ? ? ? String message = bufferedReader.readLine(); ? ? ? ? ? ? ? ? System.out.println(message); ? ? ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? ? ? throw new RuntimeException(e); ? ? ? ? ? ? } ? ? ? ? } ? ? } }
項(xiàng)目結(jié)構(gòu)如下圖
8 測試
先運(yùn)行LoginServer和ChatServer,再運(yùn)行多個(gè)Client
設(shè)置IDEA允許運(yùn)行多個(gè)實(shí)例
8.1 登錄
8.2 群聊
8.3 單聊
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 使用Java和WebSocket實(shí)現(xiàn)網(wǎng)頁聊天室實(shí)例代碼
- java socket實(shí)現(xiàn)聊天室 java實(shí)現(xiàn)多人聊天功能
- Java基于socket實(shí)現(xiàn)簡易聊天室實(shí)例
- java實(shí)現(xiàn)一個(gè)簡單TCPSocket聊天室功能分享
- Java Socket聊天室編程(一)之利用socket實(shí)現(xiàn)聊天之消息推送
- Java Socket聊天室編程(二)之利用socket實(shí)現(xiàn)單聊聊天室
- 用java WebSocket做一個(gè)聊天室
- 基于Tomcat7、Java、WebSocket的服務(wù)器推送聊天室實(shí)例
- Java編程實(shí)現(xiàn)基于TCP協(xié)議的Socket聊天室示例
- java利用Socket實(shí)現(xiàn)聊天室功能實(shí)例
相關(guān)文章
學(xué)習(xí)Java之如何對時(shí)間進(jìn)行格式化
當(dāng)我們在默認(rèn)情況下構(gòu)造出來的時(shí)間對象,它的時(shí)間格式并不適合我們閱讀,并且在開發(fā)時(shí),pc端、Android端、iOS端等展示的時(shí)間格式可能也并不完全一樣,本文就從這幾個(gè)問題給大家介紹如何對時(shí)間進(jìn)行格式化,感興趣的同學(xué)可以借鑒一下2023-05-05Intellij idea下使用不同tomcat編譯maven項(xiàng)目的服務(wù)器路徑方法詳解
今天小編就為大家分享一篇關(guān)于Intellij idea下使用不同tomcat編譯maven項(xiàng)目的服務(wù)器路徑方法詳解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-02-02如何實(shí)現(xiàn)nohup?java進(jìn)程號一直在變方法步驟詳解
這篇文章主要為大家介紹了如何實(shí)現(xiàn)nohup?java進(jìn)程號一直在變方法步驟詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11mybatis項(xiàng)目實(shí)現(xiàn)動(dòng)態(tài)表名的三種方法
有時(shí)在開發(fā)過程中java代碼中的表名和數(shù)據(jù)庫的表名并不是一致的,此時(shí)我們就需要?jiǎng)討B(tài)的設(shè)置表名,本文主要介紹了mybatis項(xiàng)目實(shí)現(xiàn)動(dòng)態(tài)表名的三種方法,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01PL/SQL實(shí)現(xiàn)JAVA中的split()方法的例子
這篇文章主要介紹了PL/SQL實(shí)現(xiàn)JAVA中的split()方法的例子的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07在java中判斷兩個(gè)浮點(diǎn)型(float)數(shù)據(jù)是否相等的案例
這篇文章主要介紹了在java中判斷兩個(gè)浮點(diǎn)型(float)數(shù)據(jù)是否相等的案例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10