Socket編寫簡易聊天室

總體思路:多個客戶端和服務端建立連接,客戶端之間通過服務端做中轉站傳輸數據

 

服務端

package com.ck.chat;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class Server {
	//用於存儲對應用戶的chat對象
	private Map<String,Chat> chats = new HashMap<String,Chat>();
	
	public Server() throws IOException {
		// 創建服務器並指定端口
		ServerSocket server = new ServerSocket(8888);

		while (true) {
			// 接收請求
			Socket client = server.accept();
			System.out.println("一個客戶端建立連接,ip地址:" + client.getInetAddress() + "  端口:" + client.getPort());
			//生成聊天對象
			new Thread(){
				public void run(){
					try {
						DataInputStream dis = new DataInputStream(client.getInputStream());
						//接收用戶的名字
						String name = dis.readUTF();
						//判斷用戶是否已存在
						Chat hasChat = chats.get(name);
						Chat chat = new Chat(Server.this,client,name);
						if(hasChat == null){
							System.out.println("用戶(" + name + ")成功登錄");
							chats.put(name, chat);
						}else{
							chat.sendToClient("你已登錄");
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}.start();

		}
	}

	public static void main(String[] args) {
		try {
			new Server();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 服務器轉發消息
	 * @param recvName 接收者名字
	 * @param message 消息內容
	 * @throws IOException 
	 */
	public void send(String recvName, String message) throws IOException {
		//得到接受者的聊天對象
		Chat chat = chats.get(recvName);
		//調用chat的發送消息方法
		chat.sendToClient(message);
	}

}

 

客戶端

package com.ck.chat;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {

	public Client() {
		DataOutputStream dos = null;
		try {
			// 指定服務器地址+端口
			Socket client = new Socket("localhost", 8888);

			System.out.print("請輸入用戶名:");
			BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
			dos = new DataOutputStream(client.getOutputStream());
			dos.writeUTF(getMsgFromConsole(console));
			dos.flush();
			
			new Chat(null,client,null);
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
			CloseUtil.closeAll(dos);
		} catch (IOException e) {
			e.printStackTrace();
			CloseUtil.closeAll(dos);
		}
	}

	public static void main(String[] args) throws UnknownHostException, IOException {
		new Client();
	}

	private String getMsgFromConsole(BufferedReader console) {
		try {
			return console.readLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "";
	}
}

 

Chat對象

package com.ck.chat;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * 聊天對象,用於實現數據的發送和接收
 * @author sansheng__
 *
 */
public class Chat {

	private boolean clientIsRuning = true;
	private boolean serverIsRuning = true;
	private DataOutputStream dos;

	public Chat(Server server, Socket socket, String sendName) throws IOException {

		final DataInputStream dis = new DataInputStream(socket.getInputStream());
		final DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
		final BufferedReader console = new BufferedReader(new InputStreamReader(System.in));

		this.dos = dos;

		/**
		 * 客戶端
		 */
		if (server == null) {
			
			/**
			 * 接收消息
			 */
			new Thread() {
				public void run() {
					while (clientIsRuning) {
						try {
							String msg = dis.readUTF();
							System.out.println(msg);
							if("你已登錄".equals(msg)){
								socket.close();
							}
						} catch (Exception e) {
							e.printStackTrace();
							clientIsRuning = false;
							CloseUtil.closeAll(dis);
						}
					}
				}
			}.start();
			
			
			/**
			 * 發送消息
			 */
			new Thread() {
				public void run() {
					while (clientIsRuning) {
						try {
							// 讀取客戶端發送的消息
							String msg = console.readLine();
							// 輸入byebye結束連接
							if ("byebye".equalsIgnoreCase(msg)) {
								socket.close();
								clientIsRuning = false;
							}
							if (msg != null && !"".equals(msg)) {
								dos.writeUTF(msg);
								dos.flush();
							}
						} catch (IOException e) {
							e.printStackTrace();
							clientIsRuning = false;
							CloseUtil.closeAll(dos);
						}
					}
				}
			}.start();
		}

		/**
		 * 服務端-接收消息
		 */
		if (server != null) {
			new Thread() {
				public void run() {
					while (serverIsRuning) {
						try {
							String msg = dis.readUTF();
							// System.out.println("客戶端消息:" + msg);
							int index1 = msg.indexOf(":");
							int index2 = msg.indexOf(",");
							if (index1 < 0) {
								// 沒有消息 服務器不轉發
								System.out.println(msg);
							} else {
								// 有消息 服務器轉發消息給對應的客戶端
								if (index2 < 0) {
									// 私聊 xxx:你好
									String recvName = msg.substring(0, index1);
									String message = msg.substring(index1 + 1);
									// 服務器發消息
									server.send(recvName, sendName + "對你說:" + message);
								} else {
									// 羣聊 xxx,xxx,xxx:你好
									String[] recvNames = msg.substring(0, index1).split(",");
									String message = msg.substring(index1 + 1);
									for (String name : recvNames) {
										server.send(name, sendName + "對你們說:" + message);
									}
								}
							}
						} catch (IOException e) {
							e.printStackTrace();
							serverIsRuning = false;
							CloseUtil.closeAll(dis);
						}
					}
				}
			}.start();
		}

	}

	/**
	 * 服務器給客戶端發送消息
	 * 
	 * @param message
	 * @throws IOException
	 */
	public void sendToClient(String message) throws IOException {
		dos.writeUTF(message);
		dos.flush();
	}

}

 

CloseUtil

package com.ck.chat;

import java.io.Closeable;
import java.io.IOException;
/**
 * 關流工具類
 * @author sansheng__
 *
 */
public class CloseUtil {
	
	public static void closeAll(Closeable... ios) {
		for(Closeable temp : ios){
			if(temp != null){
				try {
					temp.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

}

 

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