聊天室代碼

  • 客戶端代碼
package chat.room.server;
import java.net.Socket;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Scanner;
//客戶端讀取服務器端信息的線程
class ClientReadServer implements Runnable{
	private Socket socket;
	public ClientReadServer(Socket socket){
		this.socket = socket;
	}
	public void run(){
		//獲取服務器端輸入流
		Scanner scanner;
		try {
			scanner = new Scanner(socket.getInputStream());
			while(scanner.hasNext()){
				System.out.println(scanner.next());
			}
			scanner.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
//客戶端向服務器發送信息的線程
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("exit")){
					scanner.close();
					printStream.close();
					break;
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
public class MultiClient{
	public static void main(String[] args) throws IOException{
		//客戶端連接服務器端,返回套接字Socket對象
		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();
	}
}
  • 服務器端代碼
package chat.room.server;
import java.net.Socket;
import java.net.ServerSocket;
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;
import java.io.PrintStream;
import java.io.IOException;
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("");
					//1.註冊用戶流程,註冊用戶格式爲:userName:用戶名
					if(msg.startsWith("userName:")){
						//將用戶名保存在userName中
						String userName = msg.split("\\:")[1];
						//註冊用戶
						userRegist(userName,socket);
						continue;
					}
					//2.羣聊信息流程,羣聊的格式爲:G:羣聊信息
					else if(msg.startsWith("G:")){
						//必須先註冊纔可以
						firstStep(socket);
						//保存羣聊信息
						String str = msg.split("\\:")[1];
						//發送羣聊信息
						groupChat(socket,str);
						continue;
					}
					//3.私聊信息流程,私聊的格式爲:P:userName-私聊信息
					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;
					}
					//4.用戶退出流程,用戶退出格式爲:包含exit
					else if(msg.contains("exit")){
						//必須先註冊纔可以
						firstStep(socket);
						userExit(socket);
						continue;
					}
					//其他輸入格式均錯誤
					else{
						PrintStream printStream = new PrintStream(socket.getOutputStream());
						printStream.println("輸入格式錯誤,請按照以下格式輸入");
						printStream.println("註冊用戶格式:[userName:用戶名]");
						printStream.println("羣聊格式:[G:羣聊信息]");
						printStream.println("私聊格式:[P:userName-私聊信息]");
						printStream.println("用戶退出格式[包含exit即可]");
						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.getKey()==null){
	                    PrintStream printStream=new PrintStream(socket.getOutputStream());
	                    printStream.println("請先進行註冊操作!");
	                    printStream.println("註冊格式爲:[userName:用戶名]");
	                }
	            }
	        }
	    }
private void userRegist(String userName,Socket socket){
	map.put(userName,socket);
	System.out.println("[用戶名爲"+userName+"][客戶端爲"+socket+"]上線了!");
	System.out.println("當前在線人數爲:"+map.size()+"人");
}
private void userExit(Socket socket){
	//利用socket取得對應的key值
	String userName = null;
	for(String key:map.keySet()){
		if(map.get(key).equals(socket)){
			userName = key;
			break;
		}		
	}
	//將userName,Socket元素從map集合中刪除
	map.remove(userName,socket);
	//提醒服務器客戶端已下線
	System.out.println("用戶:"+userName+"已下線");
}
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+"私聊說:"+msg);
}
private void groupChat(Socket socket,String msg) throws IOException{
	//將Map集合轉換爲Set集合
	Set<Map.Entry<String,Socket>> set = map.entrySet();
	//遍歷Set集合找到發起羣聊信息的用戶
	String userName = null;
	for(Map.Entry<String, Socket> entry:set){
		if(entry.getValue().equals(socket)){
			userName = entry.getKey();
			break;
		}
	}
	//遍歷Set集合將羣聊信息發給每一個客戶端
	for(Map.Entry<String,Socket> entry:set){
		//取得客戶端的Socket對象
		Socket client = entry.getValue();
		//取得client客戶端的輸出流
		PrintStream printStream = new PrintStream(client.getOutputStream());
		printStream.println(userName+"羣聊說:"+msg);
	}
}
}
public class MultiServer{
	public static void main(String[] args){
		try{
		//1.創建服務器端的ServerSocket對象,等待客戶端連接
		ServerSocket serverSocket = new ServerSocket(6666);
		//2.創建線程池,從而可以處理多個客戶端
		ExecutorService executorService = Executors.newFixedThreadPool(20);
		for(int i=0;i<20;i++){
			System.out.println("歡迎來到我的聊天室……");
			//3.監聽客戶端
			Socket socket = serverSocket.accept();
			System.out.println("有新的朋友加入……");
			//啓動線程
			executorService.execute(new Server(socket));
		}
		//關閉線程池
		executorService.shutdown();
		//關閉服務器
		serverSocket.close();
	} catch(IOException e){
		e.printStackTrace();
	}
}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章