本文實例為大家分享了Java實現局域網聊天的具體代碼,供大家參考,具體內容如下
開發環境:
IDEA 2018.2 集成開發工具。
實現功能:
1、用戶上線,向服務器通知并注冊。
2、同局域網下,所有注冊用戶可以進行群聊。
3、同局域網下,所有用戶可與任意已注冊用戶進行私聊。
4、用戶下線,通知服務器,服務器更新信息。
實現原理:
1、服務器端實例化一個ServerSocket對象,調用accept方法等待客戶端連接到服務器。
2、客戶端實例化 Socket 對象,并使用構造方法與服務器建立鏈接。
3、服務器端根據客戶端輸入信息,辨別客戶端請求的功能從而做出相應響應。
實用技術:
為了能夠高效的處理客戶端的請求,在服務器端使用多線程處理客戶端請求。并且使用 ConcurrentHashMap 來存儲所有注冊過的客戶端。
項目源碼(解釋寫在代碼的注釋當中):
服務器端:
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 {
? ? //存儲所有注冊的客戶端
? ? private static Map<String, Socket> clientMap = new ConcurrentHashMap<String,Socket>();
? ? //具體的處理每個客戶端的請求
? ? 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要轉換為空字符串
? ? ? ? ? ? ? ? ? ? ? ? Pattern pattern = Pattern.compile("\r");
? ? ? ? ? ? ? ? ? ? ? ? Matcher matcher = pattern.matcher(strFromClient);
? ? ? ? ? ? ? ? ? ? ? ? strFromClient = matcher.replaceAll("");
? ? ? ? ? ? ? ? ? ? ? ? //注冊流程
? ? ? ? ? ? ? ? ? ? ? ? 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;
? ? ? ? ? ? ? ? ? ? ? ? ? ? //根據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("當前共有用戶" + clientMap.size() + "人");
? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? else{
? ? ? ? ? ? ? ? ? ? ? ? ? ? PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8");
? ? ? ? ? ? ? ? ? ? ? ? ? ? out.println("輸入錯誤。。。");
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? private void registerUser(String name,Socket client){
? ? ? ? ? ? System.out.println("用戶:" + name + "已上線!");
? ? ? ? ? ? clientMap.put(name,client);
? ? ? ? ? ? System.out.println("當前在線人數:" + clientMap.size() + "人!");
? ? ? ? ? ? //既然是用戶在注冊,所以這里服務器通知用戶注冊結果
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8");
? ? ? ? ? ? ? ? out.println("用戶注冊成功!");
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? private void groupChat(String msg,Socket client){
? ? ? ? ? ? //取出clientMap中所有的Entry對象,遍歷每個用戶,并且發送消息
? ? ? ? ? ? Set<Map.Entry<String,Socket>> clientSet = clientMap.entrySet();
? ? ? ? ? ? for(Map.Entry<String,Socket> entry:clientSet){
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? Socket socket = entry.getValue();
? ? ? ? ? ? ? ? ? ? //取得輸出流,向客戶端發送消息
? ? ? ? ? ? ? ? ? ? PrintStream out = new PrintStream(socket.getOutputStream(),true,"UTF-8");
? ? ? ? ? ? ? ? ? ? out.println("由端口號為"+ client.getPort() + "發來的群聊消息:" + 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("由端口號為:" + client.getPort() + "發來的消息:" + msg);
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? public static void main(String[] args)throws Exception{
? ? ? ? //為了提高效率,這里使用多線程進行處理
? ? ? ? ExecutorService executorService = Executors.newFixedThreadPool(30);
? ? ? ? //實例化ServerSocket對象,并指定IP為本地主機,端口號為6666
? ? ? ? ServerSocket serverSocket = new ServerSocket(6666);
? ? ? ? for(int i = 0; i < 30;i++){
? ? ? ? ? ? System.out.println("等待用戶連接。。。");
? ? ? ? ? ? //等待客戶端連接服務器
? ? ? ? ? ? Socket client = serverSocket.accept();
? ? ? ? ? ? System.out.println("有客戶端連接,端口號為:" + client.getPort());
? ? ? ? ? ? //啟動線程,并處理客戶端請求
? ? ? ? ? ? executorService.submit(new ExcuteClient(client));
? ? ? ? }
? ? ? ? //關閉線程,關閉服務器
? ? ? ? executorService.shutdown();
? ? ? ? serverSocket.close();
? ? }
}
客戶端:
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
?
/**
?* ?接收服務端發來的消息
?*/
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("服務器:" + in.nextLine());
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? //判斷客戶端是否退出,如果推出,跳出循環,并關閉流
? ? ? ? ? ? ? ? if (client.isClosed()) {
? ? ? ? ? ? ? ? ? ? System.out.println("客戶端關閉。。。");
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? in.close();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
}
?
/**
?* ?向服務端發出消息
?*/
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("請輸入信息:");
? ? ? ? ? ? ? ? String strToserver;
? ? ? ? ? ? ? ? if(scanner.hasNextLine()){
? ? ? ? ? ? ? ? ? ? strToserver = scanner.nextLine().trim();
? ? ? ? ? ? ? ? ? ? out.println(strToserver);
? ? ? ? ? ? ? ? ? ? //客戶端退出標志: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 {
? ? ? ? ? ? //實例化Socket對象,與服務器建立連接
? ? ? ? ? ? Socket client = new Socket("127.0.0.1",6666);
? ? ? ? ? ? //為了發送消息和接收消息可以同時進行,使用多線程進行處理
? ? ? ? ? ? Thread thread1 = new Thread(new FromServer(client));
? ? ? ? ? ? Thread thread2 = new Thread(new ToServer(client));
? ? ? ? ? ? thread1.start();
? ? ? ? ? ? thread2.start();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
}
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持html5模板網。
【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!