TCP多人聊天室

TCP多人聊天室的實現

1. 功能分析

1.1 客戶端
  1. 功能:
    1. 數據發送
    2. 數據接收
  2. 聊天:
    1. 羣聊
    2. 私聊
1.2 服務器
  1. 功能:
    1. 數據轉發
    2. 用戶註冊
  2. 數據轉發判斷:
    1. 私聊
    2. 羣聊
      我們需要知道一點:一個用戶對應着一個socket,所以我們需要將用戶和socket進行綁定,我們可以使用Map來進行存儲,Key用來存儲用戶id,Value用來存儲對應的socket

代碼

1. 服務器
public class Server{
	private HashMap<Integer, UserSocket> userMap;
	//累計訪問人數,作爲用戶的id(userMap中的Key值)
	private static int count = 0;
	//初始化
	public Server () {
		userMap = new HashMap<>();
	}
	//服務器啓動方法
	public void start() throws IOException {
		//啓動服務器,監聽端口
		ServerSocket serverSocket  = new ServerSocket(8888);
		System.out.println("服務器啓動");
		while (true) {
			//接收用戶請求
			Socket socket = serverSocket .accept();
			count += 1;
			UserSocket userSocket = new UserSocket(count, socket);
			userMap.put(count, userSocket);
			
			// 啓動當前UserSocket服務
			new Thread(userSocket).start();
		}
	}
	class UserSocket implements Runnable {
		private DataInputStream inputstream;
		private DataOutputStream outputStream;
		//用戶id
		private int userId;
		//用戶名 ,這個是剛開始註冊的時候客戶端發送給服務器的
		private String userName;
		//連接標記
		private boolean connection;
		
		//構造方法
		public UserSocket(int userId, Socket socket) {
			this.userId = userId;
			try {
				inputStream = new DataInpuStream(socket.getInputStream());
				outputStream = new DataOutputStream(socket.getOutputStream());
				connection = true;
			} catch (IOException e) {
				e.printStackTrace();
				connetion = false;
			}
			try {
				this.userName = InputStream.readUTF();
				//廣播所有人XXX上線了,自己除外
				sendOther ("ID:" + this.userId + " " + this.userName + "來到直播間", true);
				send("歡迎來到聊天室");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		/*
		* 接收客戶端發送的數據,用於轉發操作
		*/
		public String receive() {
			String msg = null;
			try {
				msg = inputStream.readUTF();
			} catch  (IOException e)  {
				e.printStackTrace();
				connetion = false;
				//設置的工具類,關閉資源
				CloseUtil.closeAll(inputStream, outputStream);
			}
			return msg;
		}
		/*
		* 發送數據到客戶端
		*/
		public void send(String msg) {
			try{
				outputStream.writeUTF(msg);
				outputStream.flush();
			} catch (IOException e) {
				e.printStackTrace();
				connetion = false;
				CloseUtil.closeAll(inputStream, outputStream);
			}
		}
		public void sendOther(String msg, boolean sys) {
			//私聊@1:XXXXXX
			if (msg.startsWith("@") && msg.contains(":")) {
				//獲取私聊的id
				Integer id = Integer.parseInt(msg.substring(1, msg.indexOf(":")));
				String newMsg = msg.substring(msg.indexOf(":"));

				UserSocket userSocket = userMap.get(id);
				if (userSocket != null) {
					userSocket.send("ID:" + this.userId + " " + this.userName + "悄悄的對你說" + newMsg);
				}
			} else {
				//羣聊
				Collection<UserSocket> values = userMap.values();
				for (UserSocket userSocket : values) {
					if (userSocket != this) {
    					// 判斷是不是系統消息
    						if (sys) {
        							userSocket.send("系統公告:" + msg);
    						} else {
        							userSocket.send("ID:" + this.userId + " " + this.userName + msg);
   						}
					}
				}
			}
		}
		@Override
		public void run() {
    			while (connetion) {
        			// 使用receive收到的消息作爲參數,同時標記非系統消息,調用sendOther
        			sendOther(receive(), false);
   			}
		}
	}
	public static void main (String[] args) {
		Server server = new Server();
		try {
   			server.start();
		} catch (IOException e) {
    			e.printStackTrace();
		}

	}
}
2. 工具類

在這裏插入圖片描述

3. 客戶端
3.1

在這裏插入圖片描述

3.2 ClientSend
public calss ClientSend implements Runnable {
	private DataOutputStream outputStream;
	
	private BufferedReader console;

	private boolean connection;
	
	public ClientSend(Socket socket, String userName) {
		try {
    			outputStream = new DataOutputStream(socket.getOutputStream());
    			console = new BufferedReader(new InputStreamReader(System.in));
    			
    			send(userName);
    			connection = true;
   		} catch (IOException e) {
    			e.printStackTrace();
    			connection = false;
    			CloseUtil.closeAll(outputStream, console);
		}
	}

	//從鍵盤上獲取用戶輸入的數據
	public String getMsgFromConsole() {
    		String msg = null;
    		try {
    			// 從鍵盤上讀取一行數據
    			msg = console.readLine();
		} catch (IOException e) {
    			e.printStackTrace();
    			connection = false;
    			CloseUtil.closeAll(outputStream, console);
		}
		return msg;
	}
	//發送數據給服務器
	public void send(String msg) {
		try {
			if (msg != null && !"".equals(msg)) {
				outputStream.writeUTF(msg);
				outputStream.flush();
			}
		} catch  (IOException e) {
			e.printStackTrace();
			connection = false;
			CloseUtil.closeAll(outputStream, console);
		}
	}
	@Override
	public void run() {
    		while (connection) {
        			send(getMsgFromConsole());
   		}
	}
}
3.3 ClientReceive
public class ClientReceive implements Runnable {
	private DataInputStream inputStream;
	private boolean connection;
	public ClientReceive(Socket socket) {
    		try {
        			inputStream = new DataInputStream(socket.getInputStream());
        			connection = true;
    		} catch (IOException e) {
        			e.printStackTrace();
        			connection = false;
    		}
	}
	public void receive() {
		String msg = null;
		try {
    			msg = inputStream.readUTF();
		} catch (IOException e) {
    			e.printStackTrace();
    			connection = false;
   			CloseUtil.closeAll(inputStream);
		}
		System.out.println(msg);
	}
	@Override
	public void run() {
    		while (connection) {
        			receive();
    		}
	}
}
4. 效果

在這裏插入圖片描述
在這裏插入圖片描述

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