文档章节

Java实现的聊天室

nekocode
 nekocode
发布于 2014/02/16 17:02
字数 1020
阅读 234
收藏 1




配置类:

public class Setting {
	public static String SERVER_IP = "127.0.0.1";
	public static int SERVER_PORT = 5250;
	
	public static String COMMAND_LOGIN = "login";
	public static String COMMAND_LOGIN_SUC = "login_suc";
	public static String COMMAND_LOGIN_FAILED = "login_failed";
	public static String COMMAND_LOGOUT = "logout";
	public static String COMMAND_SENDMSG = "sendmsg";
	
	public static String COMMAND_USERLIST = "userlist";
	public static String COMMAND_MSG = "msg";
}


服务端:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

class Server {
	private ServerSocket socket_server;
	private int port;
	private Map<String, Socket> map_client_socket;
	
	public static void main(String args[]){
		try {
			new Server(Setting.SERVER_PORT).start();
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
	}
	
	public Server(int _port) throws IOException {
		this.port = _port;
		map_client_socket = new HashMap<String, Socket>();
	}
	
	public void start() throws IOException {
		try {
		    socket_server = new ServerSocket(port);
		    while(true) {
		    	Socket socket_connection = socket_server.accept();
		    	new ListenService(socket_connection).start();
		    }
		} catch (IOException e) {
			System.out.println("初始化错误");
			throw e;
		}
	}
	
	class ListenService extends Thread {
		private Socket socket;
		private String user_name;
		private boolean logined = false;
		private BufferedReader in = null;
		
		public ListenService(Socket _socket) {
			try {
				socket = _socket;
				in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		public void run() {
			try {
				String command = "";
				while(true) {
					if((command = in.readLine()) != null) {
						if(!logined) {
							if(command.equals(Setting.COMMAND_LOGIN)) {
								user_name = in.readLine();	//读取用户名
								
								//如果用户名存在则发送无法登陆消息并关闭连接
								if(map_client_socket.containsKey(user_name)) {
									sendMsg(socket, Setting.COMMAND_LOGIN_FAILED);
									in.close();
									socket.close();
									break;
								}
								
								//将socket放入map中
								map_client_socket.put(user_name, socket);
								
								String msg = Setting.COMMAND_LOGIN_SUC + "\n" + user_name;
								sendMsgToAll(msg);
								updateUserList();
								logined = true;
							}
						} else {
						 	if(command.equals(Setting.COMMAND_LOGOUT)) {
						 		in.close();
						 		socket.close();
						 		map_client_socket.remove(user_name);
						 		
						 		String msg = Setting.COMMAND_LOGOUT + "\n" + user_name;
						 		sendMsgToAll(msg);
						 		updateUserList();
						 		break;
						 	} else if(command.equals(Setting.COMMAND_SENDMSG)) {
						 		String dest_username = in.readLine();	//读取目标用户名
						 		String msg = Setting.COMMAND_MSG + "\n" 
						 				+ user_name + "\n" //将发送者的用户名发过去
						 				+ in.readLine();
							
						 		if(dest_username.equals("所有人")) {
						 			sendMsgToAll(msg);
						 		} else {
						 			sendMsg(dest_username, msg);
						 		}
						 	}
						}
					}

				}
			} catch (IOException e) {
				e.printStackTrace();
				map_client_socket.remove(user_name);
		 		updateUserList();
			}
		}
		
		public void sendMsg(Socket dest_socket, String message) {
			try {
				PrintWriter out = new PrintWriter(new BufferedWriter(
						new OutputStreamWriter(dest_socket.getOutputStream())),true);
				out.println(message);
				out.flush();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		public void sendMsg(String dest_username, String message) {
			Socket dest_socket = map_client_socket.get(dest_username);
			sendMsg(dest_socket, message);
		}
		
		public void sendMsgToAll(String message) {
			try {
				for(Iterator<Entry<String, Socket>> itor = map_client_socket.entrySet().iterator(); itor.hasNext();) {
					Entry<String, Socket> entry = (Entry<String, Socket>)itor.next();
					
					Socket dest_socket = entry.getValue();
					PrintWriter out = new PrintWriter(new BufferedWriter(
							new OutputStreamWriter(dest_socket.getOutputStream())),true);
					out.println(message);
					out.flush();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		public void updateUserList() {
			String msg = Setting.COMMAND_USERLIST + "\n";
			
			for(Iterator<Entry<String, Socket>> itor = map_client_socket.entrySet().iterator(); itor.hasNext();) {
				Entry<String, Socket> entry = (Entry<String, Socket>)itor.next();
				msg += entry.getKey() + "|";
			}
			
			sendMsgToAll(msg);
		}
	}
}



客户端:

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

public class Client extends JFrame implements ActionListener {
	private static final long serialVersionUID = 2389760719589425440L;
	private String user_name;
	private Socket socket;
	JTextPane text_history;
	Document docs_history;
	JTextArea text_in;
	JButton btn_send;
	JLabel label_destuser;
	JComboBox<String> cbbox_destuser;
	SimpleAttributeSet attrset_cmd = new SimpleAttributeSet();
	SimpleAttributeSet attrset_msg = new SimpleAttributeSet();
	PrintWriter out = null;
	
	public static void main(String args[]) {
		try {
			String name = JOptionPane.showInputDialog("请输入用户名:","user1");
			if(name == null || name.length() == 0)
				return;
			
			Socket socket = new Socket(Setting.SERVER_IP, Setting.SERVER_PORT);
			new Client(name, socket);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
	
	public Client(String _user_name, Socket _socket) throws IOException {
		super("聊天室 - " + _user_name);
		this.setLayout(null);
		this.setBounds(200, 200, 500, 480);
		this.setResizable(false);
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		this.addWindowListener(new CloseHandler());
		
		user_name = _user_name;
		socket = _socket;
		
		text_history = new JTextPane();
		text_history.setBounds(5, 5, 485, 290);
		text_history.setEditable(false);
		JScrollPane scroll_text_history = new JScrollPane(text_history);
		scroll_text_history.setBounds(5, 5, 485, 290);
		this.add(scroll_text_history);
		docs_history = text_history.getDocument();
		
		text_in = new JTextArea();
		text_in.setBounds(5, 305, 485, 110);
		text_in.setLineWrap(true);
		text_in.setEnabled(false);
		JScrollPane scroll_text_in = new JScrollPane(text_in);
		scroll_text_in.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		scroll_text_in.setBounds(5, 305, 485, 110);
		this.add(scroll_text_in);
		
		btn_send = new JButton("发送(alt+回车)");
		btn_send.setBounds(370, 420, 120, 25);
		btn_send.addActionListener(this);
		btn_send.setEnabled(false);
		btn_send.setMnemonic(KeyEvent.VK_ENTER);
		this.add(btn_send);
		
		label_destuser = new JLabel("发送给:");
		label_destuser.setBounds(215, 420, 50, 25);
		this.add(label_destuser);
		
		cbbox_destuser = new JComboBox<String>();
		cbbox_destuser.setBounds(265, 420, 100, 25);
		this.add(cbbox_destuser);
		
		StyleConstants.setForeground(attrset_cmd, Color.BLUE);
		StyleConstants.setBold(attrset_cmd, true);
		
		StyleConstants.setForeground(attrset_msg, Color.BLACK);
		
		this.setVisible(true);
		out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
		new ListenService(user_name, socket).start();
	}
	
	class CloseHandler extends WindowAdapter {
		public void windowClosing(final WindowEvent ev) {
			try {
				out.println(Setting.COMMAND_LOGOUT);
				out.flush();
				out.close();
				socket.close();
				System.exit(0);
			} catch (IOException e) {
				e.printStackTrace();
				System.exit(0);
			}
		}
	}
	
	@Override
	public void actionPerformed(ActionEvent ev) {
		if(ev.getActionCommand()=="发送(alt+回车)") {
			String dest_user = (String)cbbox_destuser.getSelectedItem();
			if(dest_user == null)
				return;
			
			String msg = text_in.getText();
			insertText("[我] 对 [" + dest_user +  "] 说: (" + getTime() + ")\n", attrset_cmd);
			insertText(msg + "\n", attrset_msg);
			
			out.println(Setting.COMMAND_SENDMSG);
			out.println(dest_user);
			out.println(msg.replaceAll("\\n", "\\\\n"));
			out.flush();
			
			text_in.setText("");
		}
	}

	public void insertText(String str, SimpleAttributeSet attrset) {
		try {
			docs_history.insertString(docs_history.getLength(), str, attrset);
		} catch (BadLocationException ble) {
			System.out.println("BadLocationException:" + ble);
		}
	}
	
	public String getTime() {
		SimpleDateFormat df = new SimpleDateFormat("hh:mm:ss");
		return df.format(new Date());
	}
	
	class ListenService extends Thread {
		private Socket socket;
		private String user_name;
		private BufferedReader in = null;
		private PrintWriter out = null;
		
		public ListenService(String _user_name, Socket _socket) {
			try {
				user_name = _user_name;
				socket = _socket;
				in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		public void run() {
			try {
				String command = "";
				
				//发送登陆命令
				command = Setting.COMMAND_LOGIN + "\n"
						+ user_name + "\n";
				out.print(command);
				out.flush();
				
				while(true) {
					if((command = in.readLine()) != null) {
						if(command.equals(Setting.COMMAND_MSG)) {
							String user_src = in.readLine();
							String msg = in.readLine().replaceAll("\\\\n", "\n");
							if(!user_src.equals(user_name)) {
								insertText("[" + user_src + "] 对 [我] 说: (" + getTime() + ")\n", attrset_cmd);
								insertText(msg + "\n", attrset_msg);
							}
						} else if(command.equals(Setting.COMMAND_USERLIST)) {
							String user_list = in.readLine();
							String user[] = user_list.split("\\|");
							cbbox_destuser.removeAllItems();
							
							cbbox_destuser.addItem("所有人");
							for(int i=0; i<user.length; i++) {
								if(!user[i].equals(user_name))
									cbbox_destuser.addItem(user[i]);
							}
						} else if(command.equals(Setting.COMMAND_LOGIN_SUC)) {
							String user_login = in.readLine();
							insertText("[" + user_login + "] 进入了聊天室. (" + getTime() + ")\n", attrset_cmd);
							text_in.setEnabled(true);
							btn_send.setEnabled(true);
						} else if(command.equals(Setting.COMMAND_LOGIN_FAILED)) {
							insertText(user_name + "登陆失败\n", attrset_cmd);
						} else if(command.equals(Setting.COMMAND_LOGOUT)) {
							String user_logout = in.readLine();
							insertText("[" + user_logout + "] 退出了聊天室. (" + getTime() + ")\n", attrset_cmd);
						}
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}


© 著作权归作者所有

nekocode

nekocode

粉丝 19
博文 71
码字总数 77997
作品 1
广州
程序员
私信 提问
加载中

评论(0)

Python 聊天室 II(SimpleXMLRPCServer模块实现)

并不是上一个用SocketServer的聊天室的延续。用远程调用完成的聊天室。 正好有Java的RMI聊天室的作业,就先用Python写了一个简单的类似远程调用的东西,逻辑完成之后,在Java上写一遍也是水到...

FuniK
2012/12/19
776
0
Android基于XMPP Smack Openfire下学习开发IM(三)会议室创建、加入以及查询

openfire 中的会议室不像QQ群一样,不能保存那些离线用户,加入会议室后,一旦断开连接,就会离开会议室。 虽然如此,但如果要实现也不是不可能,我们可以自己做后台来保存,有兴趣的可以去试...

程序袁_绪龙
2014/11/27
724
0
jsp聊天室如何实现,大家有没有做过聊天室?

聊天室如何实现,希望是 [jsp/java/开源框架] 这些技术实现的,本人比较了解,大家有没有做过聊天室?有个项目需要开发聊天室功能,没接触过,上来请教下大家,感谢先了!

潘深练GS
2013/11/15
948
6
Android基于XMPP Smack Openfire下学习开发IM(四)单人聊天和多人聊天(发送

很久没有写博客了,回顾了一下原先学习的,接着没有写完的继续写咯。(ps:告诉大家一个秘密,其实写写博客对自己的帮助是非常大的哦~) 好了废话不多说,进入主题吧。 一、单人聊天 1)发送...

程序袁_绪龙
2014/11/27
583
1
java MyEclipse的仿qq聊天室

java聊天室想要实现qq聊天界面的改变字体的功能,求助各位大神

迷人
2016/12/19
694
0

没有更多内容

加载失败,请刷新页面

加载更多

略谈分布式系统中的容器设计模式

本文作者:zytan_cocoa 略谈分布式系统中的容器设计模式 谭中意 2020/3/5 前言:云原生(Cloud Native)不仅仅是趋势,更是现在进行时,它是构建现代的,可弹性伸缩的,快速迭代的计算网络服...

百度开发者中心
03/11
10
0
创建将T约束为枚举的泛型方法 - Create Generic method constraining T to an Enum

问题: I'm building a function to extend the Enum.Parse concept that 我正在构建一个函数来扩展Enum.Parse概念, Allows a default value to be parsed in case that an Enum value is ......

javail
今天
31
0
使用PHP的“注意:未定义的变量”,“注意:未定义的索引”和“注意:未定义的偏移量”

问题: I'm running a PHP script and continue to receive errors like: 我正在运行PHP脚本,并继续收到如下错误: Notice: Undefined variable: my_variable_name in C:\\wamp\\www\\mypat......

技术盛宴
今天
8
0
算法 : 一个整形一维数组,以及一个目标数,写一个方法,求出数组元素之和为该目标值的所有组合。

一个整形一维数组,以及一个目标数,写一个方法,求出数组任意两个元素之和为该目标值的所有组合。 function meetGroup($array, $hit){ $meet_groups =[]; foreach ($array as $...

冻结not
今天
35
0
win10下docker中安装sqlserver并使用navicat premiun连接

搜索镜像:docker search mssql 下载镜像:docker pull microsoft/mssql-server-linux 运行镜像:docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=[包含大小写字母、数字的长度不少于8位数的......

nie_yuange
今天
28
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部