用java编写一个简单的聊天室,实现私聊和多人聊天,做成图形用户界面的形式

用java编写一个简单的聊天室,实现私聊和多人聊天,做成图形用户界面的形式_第1张图片
客户端代码如下:
package client;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;

import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

import server.User;

public class Client {

private JFrame frame;
private JTextArea textArea;

private JTextField textField;

private JTextField txt_port;
private JTextField txt_hostIp;
private JTextField txt_name;

private JButton start;
private JButton stop;
private JButton send;

private JRadioButton groupchat;//群聊按钮
private JRadioButton privatechat;//私聊按钮
private ButtonGroup   buttongroup;//按钮组
private JPanel buttonPanel;
private JPanel northPanel;
private JPanel southPanel;

private JScrollPane rightScroll;
private JScrollPane leftScroll;//滚动窗格
private JSplitPane centerSplit;


private JList userList;
private DefaultListModel listModel;

private boolean isConnected = false;

private Socket socket;
private PrintWriter writer;
private BufferedReader reader;
private MessageThread messageThread;// 负责接收消息的线程
private Map onLineUsers = new HashMap();// 所有在线用户,可以和他们私聊

// 主方法
public static void main(String[] args) {
new Client();
}
public Client(){
textArea = new JTextArea();
textArea.setEditable(false);

	textField = new JTextField();
	txt_port = new JTextField("12345");
	txt_hostIp = new JTextField("127.0.0.1");
	Random rand = new Random();

	
	txt_name = new JTextField("用户" + rand.nextInt(100));
	start = new JButton("连接");
	stop = new JButton("断开");
	send = new JButton("发送");
	listModel = new DefaultListModel();
	userList = new JList(listModel);

	northPanel = new JPanel();
	northPanel.setLayout(new GridLayout(1, 7));
	northPanel.add(new JLabel("端口"));
	northPanel.add(txt_port);
	northPanel.add(new JLabel("服务器IP"));
	northPanel.add(txt_hostIp);
	northPanel.add(new JLabel("昵称"));
	northPanel.add(txt_name);
	northPanel.add(start);
	northPanel.add(stop);
	northPanel.setBorder(new TitledBorder("连接信息"));

	rightScroll = new JScrollPane(textArea);
	rightScroll.setBorder(new TitledBorder("消息显示区"));
	leftScroll = new JScrollPane(userList);
	leftScroll.setBorder(new TitledBorder("在线用户"));
	
	groupchat=new JRadioButton("群聊");
	privatechat=new JRadioButton("私聊");

	privatechat.setSelected(true);
	buttongroup=new ButtonGroup();
	buttongroup.add(groupchat);
	buttongroup.add(privatechat);
	buttonPanel=new JPanel();
	buttonPanel.setLayout(new FlowLayout());
	buttonPanel.add(groupchat);
	buttonPanel.add(privatechat);

	southPanel = new JPanel(new BorderLayout());
	southPanel.add(buttonPanel, "North");
	southPanel.add(textField, "Center");
	southPanel.add(send, "East");
	southPanel.setBorder(new TitledBorder("写消息"));

	centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftScroll,rightScroll);
	centerSplit.setDividerLocation(100);

	frame = new JFrame("客户机");
	
	frame.setLayout(new BorderLayout());
	
	frame.add(northPanel, "North");
	frame.add(centerSplit, "Center");
	frame.add(southPanel, "South");
	frame.setSize(600, 400);
	frame.setVisible(true);
	 
			// 单击发送按钮事件
			send.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					send();
				}
			});
	 
			// 单击连接按钮事件
			start.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					int port;
					if (isConnected) {
						JOptionPane.showMessageDialog(frame, "已处于连接上状态,不要重复连接!",
								"错误", JOptionPane.ERROR_MESSAGE);
						return;
					}
					try {
						try {
							port = Integer.parseInt(txt_port.getText().trim());
						} catch (NumberFormatException e2) {
							throw new Exception("端口号不符合要求!端口为整数!");
						}
						String hostIp = txt_hostIp.getText().trim();
						String name = txt_name.getText().trim();
						if (name.equals("") || hostIp.equals("")) {
							throw new Exception("昵称、服务器IP不能为空!");
						}
						boolean flag = connectServer(port, hostIp, name);					
						if (flag == false) {
							throw new Exception("与服务器连接失败!");
						}
						frame.setTitle(name);
						JOptionPane.showMessageDialog(frame, "成功连接!");
					} catch (Exception exc) {
						JOptionPane.showMessageDialog(frame, exc.getMessage(),
								"错误", JOptionPane.ERROR_MESSAGE);
					}
				}
			});
			// 单击断开按钮时事件
			stop.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					if (!isConnected) {
						JOptionPane.showMessageDialog(frame, "已处于断开状态,不要重复断开!",
								"错误", JOptionPane.ERROR_MESSAGE);
						return;
					}
					try {
						boolean flag = closeConnection();// 断开连接
						if (flag == false) {
							throw new Exception("断开连接发生异常!");
						}
						JOptionPane.showMessageDialog(frame, "成功断开!");
					} catch (Exception exc) {
						JOptionPane.showMessageDialog(frame, exc.getMessage(),
								"错误", JOptionPane.ERROR_MESSAGE);
					}
				}
			});
			
			// 关闭窗口时事件
			frame.addWindowListener(new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					if (isConnected) {
						closeConnection();// 关闭连接
					}
					System.exit(0);// 退出程序
				}
			});
			

		}

	// 执行发送
	public void send() {
		if (!isConnected) {
			JOptionPane.showMessageDialog(frame, "还没有连接服务器,无法发送消息!", "错误",
					JOptionPane.ERROR_MESSAGE);
			return;
		}
		String message=textField.getText().trim();
		String selectUser="所有人";
			
		if (message == null || message.equals("")) {
			JOptionPane.showMessageDialog(frame, "消息不能为空!", "错误",
				JOptionPane.ERROR_MESSAGE);
		}
		if(groupchat.isSelected()){

			sendMessage("TOALL@"+frame.getTitle()+"@"+selectUser+"@"+message);
			
		//	System.out.println("群聊发送");
			textField.setText("");
		}
		if(privatechat.isSelected()){

			selectUser=(String)userList.getSelectedValue();
			if(selectUser==null){
				JOptionPane.showMessageDialog(frame, "请选择想私聊的用户!");
				return;
			}
			sendMessage("TOONE@"+frame.getTitle()+"@"+selectUser+"@"+message);
			String t="我@"+selectUser+"说:"+message+"\r\n";
			
			textArea.append(t);
			//textArea.setForeground(Color.BLUE);
			textField.setText("");
			
	
	}

	}	
	//连接服务器
	public boolean connectServer(int port, String hostIp, String name) {
		// 连接服务器
		try {
			socket = new Socket(hostIp, port);// 根据端口号和服务器ip建立连接
			writer = new PrintWriter(socket.getOutputStream());
			reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			// 发送客户端用户基本信息(用户名和ip地址)
			sendMessage(name + "@" + socket.getLocalAddress().toString());
			// 开启接收消息的线程
			messageThread = new MessageThread(reader, textArea);
			messageThread.start();
			isConnected = true;// 已经连接上了
			return true;
			
		} catch (Exception e) {
			textArea.append("与端口号为:" + port + "    IP地址为:" + hostIp
					+ "   的服务器连接失败!" + "\r\n");
			isConnected = false;// 未连接上
			return false;
		}
	}
	

	//发送消息
			public void sendMessage(String message) {
				
					writer.println(message);
					writer.flush();
				
			}
	//客户端主动关闭
	@SuppressWarnings("deprecation")
	public synchronized boolean closeConnection() {
		try {
			sendMessage("CLOSE");// 发送断开连接命令给服务器
			messageThread.stop();// 停止接受消息线程
			// 释放资源
			if (reader != null) {
				reader.close();
			}
			if (writer != null) {
				writer.close();
			}
			if (socket != null) {
				socket.close();
			}
			isConnected = false;
			return true;
		} catch (IOException e1) {
			e1.printStackTrace();
			isConnected = true;
			return false;
		}
	}


	// 不断接收消息的线程
	class MessageThread extends Thread {
		private BufferedReader reader;
		private JTextArea textArea;
String username=textField.getName();
		// 接收消息线程的构造方法
		public MessageThread(BufferedReader reader, JTextArea textArea) {
			this.reader = reader;
			this.textArea = textArea;
		}
 
		// 被动的关闭连接
		public synchronized void closeCon() throws Exception {
			// 清空用户列表
			listModel.removeAllElements();
			// 被动的关闭连接释放资源
			if (reader != null) {
				reader.close();
			}
			if (writer != null) {
				writer.close();
			}
			if (socket != null) {
				socket.close();
			}
			isConnected = false;// 修改状态为断开
		}
		public void run() {
			String message = null;
			while (true) {
				try {
					message = reader.readLine();
					StringTokenizer st=new StringTokenizer(message,"/@");
					
					String parts=st.nextToken();//命令
					switch(parts){
					case "CLOSE":{
						textArea.append("服务器已关闭!\r\n");
						closeCon();// 被动的关闭连接
						return;// 结束线程
					}
					case "USERLIST":{
						
					
						int size=Integer.parseInt(st.nextToken());
						String username=null;
						String  userIp=null;
						
						for(int i=0;i

}

在这里插入代码片

服务器端代码:
package server;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

public class Server extends JFrame {

private static final long serialVersionUID = 1L;
private ServerSocket serveSocket;
private ServerThread serverThread;
private ArrayList clients;
	
private JFrame frame;
private JTextArea txt1;
private JTextField txt_message;
private JTextField txt_port;
private JButton start;
private JButton send;
private JButton stop;
private JPanel northPanle;
private JPanel southPanle;
private JScrollPane leftPanle;
private JScrollPane rightPanle;
private JSplitPane centerSplit;

private JList userList;
private DefaultListModel listModel;
private boolean isStart=false;

// 主方法
public static void main(String[] args) {
new Server();

}
//构造函数
public Server(){
	frame=new JFrame("服务器");
	txt1=new JTextArea();
	txt_message=new JTextField(30);
	txt_port=new JTextField("12345");
	start=new JButton("监听此端口");
	stop=new JButton("停止服务器");
	send=new JButton("发送");
	listModel=new DefaultListModel();
	userList=new JList(listModel);
	southPanle=new JPanel(new BorderLayout());
	southPanle.setBorder(new TitledBorder("写消息"));
	southPanle.add(txt_message,BorderLayout.CENTER);
	southPanle.add(send,BorderLayout.EAST);
	
	leftPanle=new JScrollPane(userList);
	leftPanle.setBorder(new TitledBorder("在线用户"));
	
	rightPanle=new JScrollPane(txt1);
	rightPanle.setBorder(new TitledBorder("消息显示区"));
	
	centerSplit=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftPanle,rightPanle);
	centerSplit.setDividerLocation(100);
	
	northPanle=new JPanel();
	northPanle.setLayout(new GridLayout(1,6));
	northPanle.add(start);
	northPanle.add(txt_port);
	northPanle.add(stop);
	
	frame.setLayout(new BorderLayout());
	frame.add(northPanle, BorderLayout.NORTH);
	frame.add(centerSplit, BorderLayout.CENTER);
	frame.add(southPanle, BorderLayout.SOUTH);
	frame.setSize(600, 400);
	frame.setVisible(true);

// 关闭窗口事件
frame.addWindowListener(new WindowAdapter() {
@SuppressWarnings(“unused”)
public void windowclosing(WindowEvent e){
if(isStart){
closeServer();//关闭服务器
}
System.exit(0);//退出程序
}
});
@SuppressWarnings(“unused”)
int port=Integer.parseInt(txt_port.getText());
// 监听端口事件,即启动服务器
start.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(isStart){
JOptionPane.showMessageDialog(frame, “服务器已处于启动状态”,“错误”,JOptionPane.ERROR_MESSAGE);
return;
}
int port ;
try{
try{
port= Integer.parseInt(txt_port.getText());
}catch(Exception e1){
throw new Exception(“端口号 为正整数!”);
}
if (port<= 0) {
throw new Exception(“端口号 为正整数!”);

				}
				
					serverStart(port);
					txt1.append("服务器已启动,端口:"+port+",正在等待客户端连接...\r\n");
					JOptionPane.showMessageDialog(frame, "服务器成功启动");
					start.setEnabled(false);
					txt_port.setEnabled(false);
					stop.setEnabled(true);
			} catch (Exception ee) {
	JOptionPane.showMessageDialog(frame, ee.getMessage(),"错误",JOptionPane.ERROR_MESSAGE);
			}
				
		}

});
	// 单击停止服务器按钮时事件
		stop.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					if(!isStart){
						JOptionPane.showMessageDialog(frame, "服务器还未启动!", "错误",JOptionPane.ERROR_MESSAGE);
						return;
					}
					try {
						closeServer();
						start.setEnabled(true);
						txt_port.setEnabled(true);
						stop.setEnabled(false);
						txt1.append("服务器成功停止!\r\n");
						JOptionPane.showMessageDialog(frame, "服务器成功停止!");
					} catch (Exception exc) {
						JOptionPane.showMessageDialog(frame, "停止服务器发生异常!", "错误",
								JOptionPane.ERROR_MESSAGE);
					}
				}
			});
			// 单击发送按钮时事件
			send.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					send();
				}
			});
				
}




//启动服务器
public void serverStart(int port)throws java.net.BindException {
	try {
		clients=new ArrayList();
		serveSocket = new ServerSocket(port);
		serverThread = new ServerThread(serveSocket);
		serverThread.start();
		isStart=true;
	}catch(BindException e){
		isStart=false;
		throw new BindException("端口号已被占用,换一个");
	}
	catch (Exception e) {
		e.printStackTrace();
		isStart=false;
		throw new BindException("启动服务器异常");
	}
	
}
// 关闭服务器
	@SuppressWarnings("deprecation")
public void closeServer() {
		try {
			if (serverThread != null)
				serverThread.stop();// 停止服务器线程
 
			for (int i = clients.size() - 1; i >= 0; i--) {
				// 给所有在线用户发送关闭命令
				clients.get(i).getWriter().println("CLOSE");
				clients.get(i).getWriter().flush();
				// 释放资源
				clients.get(i).stop();// 停止此条为客户端服务的线程
				clients.get(i).reader.close();
				clients.get(i).writer.close();
				clients.get(i).socket.close();
				clients.remove(i);
			}
			if (serveSocket != null) {
				serveSocket.close();// 关闭服务器端连接
			}
			listModel.removeAllElements();// 清空用户列表
			isStart=false;
		} catch (IOException e) {
			e.printStackTrace();
			isStart=true;
		}
	}

	// 执行消息发送
public void send() {
	if(!isStart){
					JOptionPane.showMessageDialog(frame, "服务器未启动,不能发送消息!","错误",
						JOptionPane.ERROR_MESSAGE);
					return;
				}
				if (clients.size() == 0) {
					JOptionPane.showMessageDialog(frame, "没有用户在线,不能发送消息!", "错误",
							JOptionPane.ERROR_MESSAGE);
					return;
				}
				String message = txt_message.getText().trim();
				if (message == null || message.equals("")) {
					JOptionPane.showMessageDialog(frame, "消息不能为空!", "错误",
							JOptionPane.ERROR_MESSAGE);
					return;
				}
				sendServerMessage(message);// 群发服务器消息
				txt1.append("服务器提示:" + txt_message.getText() + "\r\n");//服务器说的话显示在服务器界面
				txt_message.setText(null);
			}

// 把后台消息发送给各个客户端
public void sendServerMessage(String message) {
		for (int i = clients.size() - 1; i >= 0; i--) {
			clients.get(i).getWriter().println("系统提示:" + message+"(群发)");//服务器获得的输出流发送给客户端界面
			clients.get(i).getWriter().flush();
		}
	}


	//每个连接到服务器的客户端,又有与之对应的一个线程来单独处理,收发消息
	 class ClientThread extends Thread{

		 Socket socket;
		 BufferedReader reader;
		 PrintWriter writer;

		private User user;
		
		public BufferedReader getReader(){
			return reader;
			
		}
		
		public PrintWriter getWriter(){
			return writer;
			
		}
		public User getUser(){
			return user;
			
		}
		
		//每个客户端对应一个客户端线程处理
		public ClientThread(Socket socket){
			try {
				this.socket=socket;
				reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
				writer=new PrintWriter(socket.getOutputStream());
				//接收客户端的基本信息
				String line=reader.readLine();
				String[] st=line.split("@");

				user=new User(st[0],st[1]);
				//反馈连接成功消息
				writer.println("系统提示:"+user.getName()+user.getIp()+"与服务器连接成功!");

				//System.out.println(user.getName()+".."+user.getIp());
				  //反馈当前用户信息
				if(clients.size()>0){
					String temp="";
					for(int i=clients.size()-1;i>=0;i--){
						temp+=(clients.get(i).getUser().getName()+"/"+clients.get(i).getUser().getIp())+"@";
						
					}
					
					writer.println("USERLIST@"+clients.size()+"@"+temp);
					writer.flush();
					
				}
				System.out.println(st[0]+",服务器显示上线"+st[1]);
				//向所有在线用户发送该用户上线命令,即把新上线的用户添加在在线用户列表中
				for(int i=clients.size()-1;i>=0;i--){
					clients.get(i).getWriter().println("ADD@"+user.getName()+"@"+user.getIp());
					clients.get(i).getWriter().flush();
				}
				
			} catch (Exception e) {
				System.out.println(e.getMessage());
				e.printStackTrace();
			}
			
		}
		@SuppressWarnings("deprecation")
		public void run(){//不断接受客户端的消息进行处理
			String message=null;
			while(true){
				try {
				  message=reader.readLine();//接收客户端消息
			
					if (message.equals("CLOSE"))// 下线命令
					{
						 txt1.append(this.getUser().getName()+ this.getUser().getIp() + "下线!\r\n");
						 
						// 断开连接释放资源
						reader.close();
						writer.close();
						socket.close();

						// 向所有在线用户发送该用户的下线命令
						for (int i = clients.size() - 1; i >= 0; i--) {
							clients.get(i).getWriter().println("DELETE@" + user.getName());
						clients.get(i).getWriter().flush();
						}

						listModel.removeElement(user.getName());// 更新在线列表
						// 删除此条客户端服务线程
						for (int i = clients.size() - 1; i >= 0; i--) {
							if (clients.get(i).getUser() == user) {
								ClientThread temp = clients.get(i);
								clients.remove(i);// 删除此用户的服务线程
								temp.stop();// 停止这条服务线程
								return;
							}
						}
						
					}else{
						dispatcherMessage(message);// 转发消息
					}

				} catch (Exception e) {
					// TODO: handle exception
				}
			}
		}

		private void dispatcherMessage(String message) {


			String[] parts=message.split("@");
			String string=parts[1]+"对"+parts[2]+"说:"+parts[3];
			if (parts[0].equals("TOALL")) {// 群发
				for (int i = clients.size() - 1; i >= 0; i--) {
					clients.get(i).getWriter().println("TOALL@"+string);
					clients.get(i).getWriter().flush();
					//System.out.println("群聊消息发送");
				}
				txt1.append(string + "\r\n");
			}
			if(parts[0].equals("TOONE")){//私发
				for(int i=0;i

// 服务器线程
class ServerThread extends Thread {
private ServerSocket serverSocket;

			// 服务器线程的构造方法
			public ServerThread(ServerSocket serverSocket) {
				this.serverSocket = serverSocket;
				
			}

			public void run() {
				while (true) {// 不停的等待客户端的链接
					try {
						Socket socket = serverSocket.accept();
						ClientThread client = new ClientThread(socket);
						client.start();// 开启对此客户端服务的线程
						clients.add(client);
						listModel.addElement(client.getUser().getName());// 更新在线列表
						txt1.append(client.getUser().getName()+ client.getUser().getIp() + "上线!\r\n");
					}catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}

}
创建的User类
package server;
public class User {
private String name;
private String ip;
public User(String name,String ip){
this.name=name;
this.ip=ip;
}
public String getName() {

	return name;
}
public void setName(String name){
this.name=name;
}
public String getIp() {
	
	return ip;
}
public void setIp(String ip){
	this.ip=ip;
	}

}

你可能感兴趣的:(java编程)