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 chats = new HashMap();
	
	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();
				}
			}
		}
	}

}

 

你可能感兴趣的:(java)