实训项目-聊天室

//服务端



import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Toolkit;
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.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;

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.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import Layout.Server.Client;
/**
 * 
 * @author 晓晓
 *
 */
public class Server {

	private JFrame frame; //创建一个swing界面
//	private JList<String> clientlist; //用户列表
	private JTextArea textArea; //输入消息的文本域
	
	public JTextArea getTextArea() {
		return textArea;
	}

	public void setTextArea(JTextArea textArea) {
		this.textArea = textArea;
	}

	private JTextField inputbox; //输入框
	private JTextField inputbox_max_people; //人数上限输入框
	private JTextField inputbox_port=null; //接口输入框
//	private JTextField textField_send;
	private JTextField inputbox_kickeduser; //被踢用户输入框
	
	private JButton btn_start; //启动按钮
	private JButton btn_pause; //暂停按钮
	private JButton btn_send; //消息发送按钮
	private JButton btn_kickuser; //踢出用户按钮
	
	private JPanel southPanel; //上方(北)界面
	private JPanel northPanel; //下方(南)界面
	
	private JScrollPane leftscrollPanel; //显示在线人员的左方滚动面板
	private JScrollPane rightscrollPanel; //显示消息的右方滚动面板
	
	//分割面板
	private JSplitPane centerSplit; 
	
	private DefaultListModel<String> listModel; //列表模型
	private JPanel kickeduser;
	private JLabel kick_user;
	private JLabel to_be_continued;
	
//	private ServerSocket server;
//	private ServerThread ServerThread;
	private boolean isStart = false;//定义一个布尔类的服务器启动标记
	int port;//设置服务器端口
	int max_people;//设置人数上限
	static ArrayList<Client> socket_xc = new ArrayList<Client>();
	ServerSocket ss = null;	//服务器
	private JList Clientlist;
	

	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Server window = new Server();
					window.frame.setVisible(true);
					window.frame.addWindowListener(new WindowAdapter() {
						
						//增加一个监听器,遍历用户列表,将此服务器下线广播到每一个用户
						
						@Override
						public void windowClosing(WindowEvent arg0) {
							for(Client client:socket_xc) {
								String send_massage = "WARNING@"+"服务器已下线";	//窗口提示								
								try {
									//字节输出流
									OutputStream out = client.socket.getOutputStream();//返回此套接字的输出流。
									PrintWriter write = new PrintWriter(out);
									write.println(send_massage);将信息写进字符缓冲区
									write.flush();//刷新该流的缓冲																											
								} catch (IOException e) {
									// TODO 自动生成的 catch 块
									e.printStackTrace();
								}	
							}
						
						}
					});
			
				}catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	
	}

	/**
	 * Create the application.
	 */
	public Server() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		
		textArea = new JTextArea();
		textArea.setEditable(false);
		Clientlist = new JList();
//		Clientlist.setFocusable(false);
		
		//连接信息区域的框体
		inputbox = new JTextField();
		inputbox_max_people = new JTextField();
		inputbox_max_people.setSize(58, 26);
		inputbox_max_people.setLocation(96, 29);
		inputbox_port = new JTextField("8080");
		inputbox_port.setSize(128, 28);
		inputbox_port.setLocation(420, 27);
		
		
		btn_start = new JButton("启动");
		btn_start.setSize(119, 33);
		btn_start.setLocation(561, 25);
		btn_start.addActionListener(new ActionListener() {
			//增加一个启动的监听器
			public void actionPerformed(ActionEvent arg0) {	
				start();				
			}
		});
		
		btn_pause = new JButton("暂停");
		btn_pause.setSize(112, 34);
		btn_pause.setLocation(684, 25);
		btn_pause.addActionListener(new ActionListener() {
			//增加一个暂停的监听器
			@Override
			public void actionPerformed(ActionEvent e) {
				pause();
			}
		});
		
		btn_send = new JButton("发送");
		btn_send.addActionListener(new ActionListener() {
			//增加一个发送的监听器
			public void actionPerformed(ActionEvent arg0) {
				send();		
			}
		});
		//用户列表获取
		listModel = new DefaultListModel<String>();
		JList<String> list = new JList<String>(listModel);
//		list = new JList<String>(listModel);
		list.addListSelectionListener(new ListSelectionListener() {
			
			@Override
			public void valueChanged(ListSelectionEvent arg0) {
				// TODO Auto-generated method stub
				if (!arg0.getValueIsAdjusting()) {
					// 获取所有被选中的选项索引
					int index = list.getSelectedIndex();                              
					if (index >= 0) {
						String select_Name = listModel.getElementAt(index);                      
						inputbox_kickeduser.setText(select_Name); // 根据下标获取被踢用户名字 
						}
					}
				}
			});	

		
		//连接信息部分的界面
		northPanel = new JPanel();
		northPanel.setLayout(null);
		northPanel.setBorder(new TitledBorder("连接信息"));//设置标题Title
		JLabel people_line = new JLabel("人数上限:");
		people_line.setSize(80, 22);
		people_line.setLocation(14, 33);
		northPanel.add(people_line);
		northPanel.add(inputbox_max_people);
		northPanel.setBounds(0, 0, 809, 64);
		
		JLabel port_port = new JLabel("端口:");
		port_port.setSize(58, 28);
		port_port.setLocation(358, 28);
		northPanel.add(port_port);
		northPanel.add(inputbox_port);
		northPanel.add(btn_start);
		northPanel.add(btn_pause);
		
		//中间的滚动面板部分		
		//左边在线用户面板部分
		leftscrollPanel = new JScrollPane(list);
		leftscrollPanel.setBorder(new TitledBorder("在线用户"));
		//右边消息显示区面板部分
		rightscrollPanel = new JScrollPane(textArea);
		rightscrollPanel.setBorder(new TitledBorder("消息显示区"));
		
		//分割中间部分面板
		centerSplit =new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftscrollPanel,rightscrollPanel);
		centerSplit.setSize(809, 314);
		centerSplit.setLocation(0, 72);
		centerSplit.setDividerLocation(100); //设置分割的位置为从左向右100
		
		
		
		//底部(南)面板界面
		southPanel = new JPanel(new BorderLayout());
		southPanel.setSize(811, 64);
		southPanel.setLocation(0, 387);
		southPanel.setBorder(new TitledBorder("写信息"));
		southPanel.add(inputbox,"Center"); //信息输入位置
		southPanel.add(btn_send,"East"); //发送按钮
		
		frame = new JFrame("服务端");
		frame.getContentPane().setLayout(null);
		frame.getContentPane().add(northPanel,"North");
		frame.getContentPane().add(centerSplit,"Center");
		frame.getContentPane().add(southPanel,"South");
		
		//服务器功能操作界面
		kickeduser = new JPanel();
		kickeduser.setBounds(810, 0, 192, 438);
		frame.getContentPane().add(kickeduser);
		kickeduser.setLayout(null);
		
		kick_user = new JLabel("被踢用户");
		kick_user.setSize(75, 26);
		kick_user.setLocation(2, 29);
		kickeduser.add(kick_user);
		
		inputbox_kickeduser = new JTextField();
		inputbox_kickeduser.setSize(80, 25);
		inputbox_kickeduser.setLocation(66, 30);
		kickeduser.add(inputbox_kickeduser);
		inputbox_kickeduser.setColumns(10);
		
		btn_kickuser = new JButton("踢");
		btn_kickuser.setSize(47, 26);
		btn_kickuser.setLocation(145, 29);
		btn_kickuser.addActionListener(new ActionListener() {
			//增加一个踢人的监听
			@Override
			public void actionPerformed(ActionEvent e) {
				Kick();
			}
		});
		kickeduser.add(btn_kickuser);
		
		to_be_continued = new JLabel("未完待续...");
		to_be_continued.setSize(118, 26);
		to_be_continued.setLocation(34, 219);
		kickeduser.add(to_be_continued);
		
	
		frame.setSize(1020,498);
		int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
		int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
		frame.setLocation((screen_width-frame.getWidth())/2,(screen_height-frame.getWidth())/2);
		frame.setVisible(true); //设置可见
		
}
	
	//客户发给服务器的消息
	public  class Client extends Thread{
		private Socket socket = null;
		private InputStream in = null;	
		private BufferedReader buf = null;
		private PrintWriter write =null;
		private OutputStream out = null;
		public Client() {
		
	}
		public Client(String name,Socket socket) {
			super(name);
			this.socket = socket;
		}
		@Override
		public void run() {
			try {
				
				in = socket.getInputStream();//返回输入流。
				buf = new BufferedReader(new InputStreamReader(in));
				while(true) {
					if(this.isInterrupted()) {
						//throw new InterruptedException();
						return;
					}
					String info_accept = buf.readLine();		
					System.out.println(info_accept);
					
//					StringTokenizer(String str, String delim) 
//					构造一个用来解析 str 的 StringTokenizer 对象,并提供一个指定的分隔符。
					
					StringTokenizer str = new StringTokenizer(info_accept,"@");//分割接收的信息,提取命令 
					String order = str.nextToken();//命令
					String send_massage = str.nextToken();
					
					//区分消息种类
					switch(order) {
					case "SEND_MESSAGE":
									//私聊
									if(send_massage.equals(" ")) {
										System.out.println("加入私聊");
										//私聊用户的名字
										String select_Name = str.nextToken();
										//私聊内容	
										send_massage = str.nextToken();
										//列遍每一个用户找到私聊用户和自己								
										for(Client client:socket_xc) {
											
											//找到私聊的用户
											if(client.getName().equals(select_Name)) {
												String info_send = " "+"@"+this.getName()+":"+send_massage+"(  对"+select_Name+"私聊)";
												
												out = client.socket.getOutputStream();	//返回此套接字的输出流。					
												write = new PrintWriter(out);
												write.println(info_send);//将信息写进字符缓冲区
												write.flush();//刷新该流的缓冲
												textArea.append(this.getName()+":"+send_massage+"(  对"+select_Name+"私聊)"+"\n");break;//将接收的消息打印到服务器的消息显示区
												
											}
											
											//找到自己
											if(client == this) {
												String info_send = " "+"@"+this.getName()+":"+send_massage+"(  对"+select_Name+"私聊)";
												out = client.socket.getOutputStream();//返回此套接字的输出流。		
												
												write = new PrintWriter(out);
												write.println(info_send);//将信息写进字符缓冲区
												write.flush();//刷新该流的缓冲
												textArea.append(info_send);break;
											}
										}
										
									}else {
										for(Client client:socket_xc) {//列遍每一个用户,将接收到的东西发送给他们
											String info_send = "SEND_MESSAGE@"+this.getName()+":"+send_massage;
											out = client.socket.getOutputStream();//返回此套接字的输出流。						
											write = new PrintWriter(out);
											write.println(info_send);//将信息写进字符缓冲区
											write.flush();//刷新该流的缓冲
										}
										textArea.append(this.getName()+":"+send_massage+"\n");//将接收的消息打印到服务器的消息显示区	
									}
									
									break;
					case "OFFLINE":	
									for(Client client:socket_xc) {//列遍每一个用户,将此用户下线信息广播出去
										if(client != this) {
											String info_send = "OFFLINE@"+this.getName();
											out = client.socket.getOutputStream();//返回此套接字的输出流。						
											write = new PrintWriter(out);
											write.println(info_send);//将信息写进字符缓冲区
											write.flush();//刷新该流的缓冲
											
										}									
									}
									listModel.removeElement(this.getName());//刷新服务器在线列表
									textArea.append("服务器:"+this.getName()+"已下线!\n");
									this.interrupt();
									
									//用迭代器遍历
									Iterator<Client> clients = socket_xc.iterator();
									while(clients.hasNext()) {//列遍每一个用户,删除下线用户
										Client client = clients.next();
										if(client == this) {
											clients.remove();
										}									
									}
									break;
					}						
				}
				
			} catch (IOException e) {
				
				e.printStackTrace();
			}
				
		}
	}

	//服务器发给客户端
	public class Accept extends Thread {
		private ServerSocket ss;
		private InputStream in = null;
		private BufferedReader buf = null;
		private OutputStream out =null;
		private PrintWriter write = null;
		public Accept() {
			
		}
		public Accept(String name) {
			super(name);
		}
		public Accept(ServerSocket ss) {
			this.ss = ss;
		}
		@Override
		public void run() {
//			Socket socket = null;
			if(isStart) {
				while(true) {
					try {
						Socket socket = ss.accept();//接收客户端的连接
						if(socket_xc.size()<max_people) {
							in = socket.getInputStream();//返回此套接字的输入流。
							buf = new BufferedReader(new InputStreamReader(in));							
							String name = buf.readLine();//接收用户信息
							StringTokenizer str = new StringTokenizer(name,"@");//分割接收的信息,提取命令 
							
							//登陆提示
							if(str.nextToken().equals("ONLINE")) {
								name = str.nextToken();//获得客户名字
								Client newclient = new Client(name,socket);//创建一个客户端线程
								newclient.start();//启动客户端线程
								socket_xc.add(newclient);//保存客户端线程
								textArea.append("服务器:欢迎用户"+newclient.getName()+"上线!\n");
								listModel.addElement(newclient.getName());
								}
							
								//将新用户上线信息广播到其它用户
							for(Client client_:socket_xc) {
								//if(client_.isInterrupted()) continue;//排除已经中断的客户线程(中断的线程还存在) 
								out = client_.socket.getOutputStream();//返回此套接字的输出流。						
								write = new PrintWriter(out);
								String info_send ="SEND_MESSAGE@服务器:欢迎用户"+name+"上线";
								write.println(info_send);将信息写进字符缓冲区
								write.flush();//刷新该流的缓冲
								String info_send_2 ="NEWCLIENT@"+name;
								write.println(info_send_2);将信息写进字符缓冲区
								write.flush();//刷新该流的缓冲
								}
							
							//将其它在线用户的名字信息广播到新用户
							for(Client client_:socket_xc) {
								if(client_.socket != socket) {				
									out = socket.getOutputStream();//返回此套接字的输出流。						
									write = new PrintWriter(out);
									String info_send ="NEWCLIENT@"+client_.getName();
									System.out.println("在线用户消息:"+info_send);
									write.println(info_send);将信息写进字符缓冲区
									write.flush();//刷新该流的缓冲
								}
							}
							
							}else {
								OutputStream out = socket.getOutputStream();//返回此套接字的输出流。						
								PrintWriter w = new PrintWriter(out);
								String info_send ="WARNING@"+"登陆服务器失败,服务器登陆人数已达上限";//提示
								w.println(info_send);将信息写进字符缓冲区
								w.flush();//刷新该流的缓冲
								}
						} catch (Exception e) {
							e.printStackTrace();
							}
					}
				}
		}
	}
	
	
	
	
	public void start() {
		try {
			if(isStart){//服务器已经启动
				JOptionPane.showMessageDialog(null,"服务器("+port+"端口)已启动!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
				return;
			}
			//判断连接信息输入合法性
			String max_peo = inputbox_max_people.getText();
			if(max_peo.equalsIgnoreCase("")) {//判断上限人数是否为空
				JOptionPane.showMessageDialog(null,"请输入有效人数上限!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
				return;
			}
			max_people = Integer.parseInt(max_peo);//获取输入的人数上限
			if(inputbox_port.getText().length() == 0) {//判断是否设置端口
				JOptionPane.showMessageDialog(null,"请输入有效端口!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
				return;
			}
			port=Integer.parseInt(inputbox_port.getText());//获取输入的服务器端口号
			//启动服务器	
			ss = new ServerSocket(port);
			isStart = true;
			//在消息区显示已经启动
			textArea.append("服务器:服务器("+port+"端口)已启动!人数上限:"+max_people+"\n");
			inputbox_port.setEditable(false);//设置端口文本域不可编辑
			inputbox_max_people.setEditable(false);//设置人数上限文本域不可编辑
//			btn_start.setEnabled(false);
			JOptionPane.showMessageDialog(null,"服务器("+port+"端口)启动成功!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
			Accept accept = new Accept(ss);//初始化接收客户端的线程
			accept.start();//启动等待客户端线程
//			ServerThread st= new ServerThread(server);
			}catch (IOException e) {
				JOptionPane.showMessageDialog(null,"服务器启动失败!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
				e.printStackTrace();
			}
	}
	
	private void pause() {
		try {
			if(!isStart) {
				JOptionPane.showMessageDialog(null,"服务器未启动!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
				return;
			}
			inputbox_port.setEditable(true);//将端口设置为可以编辑
			inputbox_max_people.setEditable(true);//设置人数上限文本域可编辑
			listModel.clear();//删除在线用户列表中的所有元素
			for(Client client:socket_xc) {//这里的格式不懂为什么for循环里面这样写
				//列遍每一个用户线程发送服务器下线通知,并将其线程中断
				String info_send = "WARNING@"+"服务器已下线";									
				OutputStream out = client.socket.getOutputStream();//返回此套接字的输出流。
				PrintWriter write = new PrintWriter(out);
				write.println(info_send);将信息写进字符缓冲区
				write.flush();//刷新该流的缓冲
				client.socket.close();
				client.interrupt();
			}
			ss.close();
			textArea.append("服务器:("+port+"端口)已关闭!\n");		
			isStart = false;
			//关闭所有相关资源(未实现)(线程,在线用户集合)
			JOptionPane.showMessageDialog(null,"服务器("+port+"端口)已关闭!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
			}catch (IOException e1) {
				JOptionPane.showMessageDialog(null,"服务器关闭失败!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
				e1.printStackTrace();
		}
	}
	
	private void send() {
		try {
			if(!isStart) {
				JOptionPane.showMessageDialog(null,"请先启动服务器", "系统信息", JOptionPane.INFORMATION_MESSAGE);
				return;
			}
			/*
			 * 定义发信息的输出流
			 */
			OutputStream out= null;
			PrintWriter write = null;
			//发送信息到各个客户端
			String info = inputbox.getText();
			inputbox.setText("");//将消息框置为空
			if(info.equals("")) {
				JOptionPane.showMessageDialog(null,"发送的内容为空", "服务器", JOptionPane.INFORMATION_MESSAGE);
				return;
			}
			textArea.append("服务器:"+info+"\n");
			String info_send = "SEND_MESSAGE@服务器:"+info;
			for(Client client:socket_xc) {//列 遍每一个用户,将接收到的东西发送给他们						
				out = client.socket.getOutputStream();//返回此套接字的输出流。						
				write = new PrintWriter(out);
				write.println(info_send);将信息写进字符缓冲区
				write.flush();//刷新该流的缓冲
			}
		}catch (IOException e) {
			JOptionPane.showMessageDialog(null,"发送消息失败", "服务器", JOptionPane.INFORMATION_MESSAGE);
			e.printStackTrace();
		}
		
	}
	
	private void Kick() {

		String kickeduser_Name = inputbox_kickeduser.getText();
		if(!kickeduser_Name.equals("")) {
			listModel.removeElement(kickeduser_Name);//从在线列表中踢出
			OutputStream out;
			PrintWriter write;										
			try {
				for(Client client:socket_xc) {			
					if(client.getName().equals(kickeduser_Name)) {						
						String clientName = "Kick"+"@"+client.getName();		
						out = client.socket.getOutputStream();
						write = new PrintWriter(out);
						write.println(clientName);将信息写进字符缓冲区
						write.flush();//刷新该流的缓冲
						socket_xc.remove(client);
						client.interrupt();	
						textArea.append("服务器:"+kickeduser_Name+"已被踢出群聊\n");
						JOptionPane.showMessageDialog(null,kickeduser_Name+"已被踢出群聊", "服务器", JOptionPane.INFORMATION_MESSAGE);																
					}else {
						String kickeduserName = "OFFLINE@"+kickeduser_Name;	
						out = client.socket.getOutputStream();
						write = new PrintWriter(out);
						write.println(kickeduserName);将信息写进字符缓冲区
						write.flush();//刷新该流的缓冲
					}
				}
			} catch (IOException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}//返回此套接字的输出流。
			
		}else {
			JOptionPane.showMessageDialog(null,"请输入或选择被踢用户!", "服务器", JOptionPane.INFORMATION_MESSAGE);
		}
			
	

	}
}

      //客户端

package Practical_Training1;
/**
 * 客户端 
 * @author 晓晓
 *
 */
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import Layout.Client;
import Practical_Training.Client.Accept_info;

import java.awt.*;
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.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UncheckedIOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;

public class ClientSide extends JFrame{
	private JFrame frame; //创建一个swing界面
//	private JList<String> clientlist; //用户列表
	private JTextArea textArea; //文本域
	
	private JTextField inputbox; //输入框
	private JTextField inputbox_port; //接口输入框
	private JTextField inputbox_ip; //ip输入框
	private JTextField inputbox_username; //用户名输入框
	
	private JButton btn_connect; //连接按钮
	private JButton btn_disconnect; //断开连接按钮
	private JButton btn_send; //消息发送按钮
	
	private JPanel southPanel; //上方(北)界面
	private JPanel northPanel; //下方(南)界面
	
	private JScrollPane leftscrollPanel; //显示在线人员的左方滚动面板
	private JScrollPane rightscrollPanel; //显示消息的右方滚动面板
	
	private JSplitPane centerSplit; //分割面板
	
	private DefaultListModel<String> listModel; //列表模型
	static ArrayList<Client> socket_xc = new ArrayList<Client>();
	
	private int port;//服务器的端口
	Accept accept;
	private String ip;//服务器地址
	private String name;//客户姓名
	private OutputStream out ;	//客户端输出流	
	private InputStream in = null;//客户端输入流				
	private PrintWriter write ;//用来创建一个文件并向文本文件写入数据
	private BufferedReader buf = null;//字符流
	boolean isConnect = false;//判断是否连接服务器的标识
	
//	构造方法
	public ClientSide() {
		
		textArea = new JTextArea();
		textArea.setEditable(false);//将消息显示区设为不可编辑
		
		
		//连接信息区域的框体
		inputbox = new JTextField();
		inputbox_username = new JTextField("xiaoxiao");
		inputbox_username.setSize(86, 24);
		inputbox_username.setLocation(60, 26);
		inputbox_ip = new JTextField("127.0.0.1");
		inputbox_ip.setSize(86, 24);
		inputbox_ip.setLocation(295, 26);
		inputbox_port = new JTextField("8080");
		inputbox_port.setSize(86, 24);
		inputbox_port.setLocation(455, 26);
		
		
		btn_connect = new JButton("连接");
		btn_connect.setSize(113, 27);
		btn_connect.setLocation(567, 25);
		btn_connect.addActionListener(new ActionListener() {
			//添加一个连接的监听器
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					if(isConnect) {
						return;
					}
					String Local_IP=InetAddress.getLocalHost().getHostAddress();//获取本机地址
					
					
//					依次判断是否输入name,ip,port
					//name
					if(inputbox_username.getText().equals("")) {
						JOptionPane.showMessageDialog(null,"未输入用户名!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
						//showMessageDialog的用法见https://www.cnblogs.com/guohaoyu110/p/6440333.html
						return;
					}
					name = inputbox_username.getText();//获取输入的客户姓名
					String username = "ONLINE@"+name+"@"+Local_IP;
					
//					解决用户名重复依旧可以登录的问题	
			
//					for(Client client:socket_xc) {			
//						if(client.getName().equals(inputbox_username.getText())) {						
//							JOptionPane.showMessageDialog(null,"用户名已存在!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
//							}
//						}
//					Iterator<Client> clients = socket_xc.iterator();
//					while(clients.hasNext()) {//列遍每一个用户
//						Client client = clients.next();
//					    String old_name = client.getName();
//					    if(inputbox_username.getText().equals(old_name)) {
//					    	JOptionPane.showMessageDialog(null,"用户名已存在!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
//					    }
//					}
					
					//ip
					if(inputbox_ip.getText().equalsIgnoreCase("")) {
						//判断是否输入IP地址
						JOptionPane.showMessageDialog(null,"未输入服务器IP!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
						return;
					}
					ip = inputbox_ip.getText();//获取输入的ip地址
					
					//port
					if(inputbox_port.getText().equals("")) {
						//判断是否输入端口号
						JOptionPane.showMessageDialog(null,"未输入服务器端口号!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
						return;
					}
					port = Integer.parseInt(inputbox_port.getText());//获取输入的服务器端口号
					
					
					//连接服务器
					Socket socket = new Socket(ip,port);
					textArea.append("服务器连接成功!\n");
					JOptionPane.showMessageDialog(null,"连接服务器成功!", "系统信息", JOptionPane.INFORMATION_MESSAGE);
					
					//将port、ip、name设为不可编辑
					inputbox_ip.setEditable(false);
					inputbox_port.setEditable(false);
					inputbox_username.setEditable(false);
					isConnect=true;
					
					accept = new Accept(socket);
					accept.start();
					out = socket.getOutputStream();//返回此套接字的输出流。					
					write = new PrintWriter(out);
					write.println(username);//将信息写进字符缓冲区
					write.flush();//刷新该流的缓冲
				} catch (UncheckedIOException e1) {
					JOptionPane.showMessageDialog(null,"连接服务器失败,请检查服务器IP和端口号是否正确", "系统信息", JOptionPane.INFORMATION_MESSAGE);
					e1.printStackTrace();
				} catch (IOException e1) {
					JOptionPane.showMessageDialog(null,"连接服务器失败,请检查服务器IP和端口号是否正确", "系统信息", JOptionPane.INFORMATION_MESSAGE);				
					e1.printStackTrace();
				}
				
			}
		});
		
		
		btn_disconnect = new JButton("断开");
		btn_disconnect.setSize(113, 27);
		btn_disconnect.setLocation(684, 25);
		btn_disconnect.addActionListener(new ActionListener() {
			//绑定一个断开连接的监听器
			@Override
			public void actionPerformed(ActionEvent e) {
				if(!isConnect) {
					return;
				}
				String Offline_name = "OFFLINE@"+name;
				
				try {
					write.println(Offline_name);//将信息写进字符缓冲区
					write.flush();//刷新该流的缓冲。
					listModel.clear();//改变用户列表
					textArea.append("服务器:用户"+name+"已下线!\n");
	
					//将port、ip、name设为可编辑
					inputbox_ip.setEditable(true);
					inputbox_port.setEditable(true);
					inputbox_username.setEditable(true);
					isConnect = false;//更改连接状态
					
					accept.interrupt();//中断客户端接收线程										
					write.close();
					buf.close();
					
					//关闭客户的输出流和输入流
					out.close();		
					in.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}	
			}
		});
		
		btn_send = new JButton("发送");
		btn_send.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
//				System.out.println("-----------------------------------------");
				// 创建一个发送的监听
				if(!isConnect) {
					JOptionPane.showMessageDialog(null,"请先连接服务器!", name, JOptionPane.INFORMATION_MESSAGE);
					return;
				}
					
				String send_massage = inputbox.getText();	
				inputbox.setText("");//将消息框置为空
				if(send_massage.equals("")) {
					JOptionPane.showMessageDialog(null,"您输入的内容为空!", name, JOptionPane.INFORMATION_MESSAGE);
					return;
				}
				textArea.append("我:"+send_massage+"\n");
				send_massage = "SEND_MESSAGE@"+send_massage;	
				write = new PrintWriter(out);
				write.println(send_massage);//将发送的信息写进字符缓冲区
				write.flush();//刷新缓冲。
				
			}
		});
		
		listModel = new DefaultListModel<String>();
		JList<String> list = new JList<String>(listModel);
		list.addListSelectionListener(new ListSelectionListener() {
			//增加一个监听,当鼠标点击用户时
            public void valueChanged(ListSelectionEvent e) {
                // 鼠标点击
                if (!e.getValueIsAdjusting()) {
                                      
                    // 获取所有被选中的选项下标
                    int index = list.getSelectedIndex();                              
                    if (index >= 0) {
                        String select_Name = listModel.getElementAt(index); // 获取选项数据(私聊名字)
                        //System.out.println("私聊用户:"+selectName);
                        
                      //不能私聊自己
                        if(!select_Name.equals(name)) {
                        	inputbox.setText(" "+"@"+select_Name+"@");
                        }                               
                    }
                }
            }
        });
		
		
		//连接信息部分的界面
		northPanel = new JPanel();
		northPanel.setLayout(null);
		northPanel.setBounds(new Rectangle(0, 0, 811, 71));
//		northPanel.setLayout(new GridLayout(1,7));
		northPanel.setBorder(new TitledBorder("连接信息"));//设置标题Title
		JLabel name_name = new JLabel("姓名:");
		name_name.setSize(54, 21);
		name_name.setLocation(14, 29);
		northPanel.add(name_name);
		northPanel.add(inputbox_username);
		JLabel ip_ip = new JLabel("服务器IP:");
		ip_ip.setSize(86, 21);
		ip_ip.setLocation(216, 28);
		northPanel.add(ip_ip);
		northPanel.add(inputbox_ip);
		JLabel port_port = new JLabel("端口:");
		port_port.setSize(54, 21);
		port_port.setLocation(405, 29);
		northPanel.add(port_port);
		northPanel.add(inputbox_port);
		northPanel.add(btn_connect);
		northPanel.add(btn_disconnect);
		
		//中间的滚动面板部分		
		//左边在线用户面板部分
		leftscrollPanel = new JScrollPane(list);
		leftscrollPanel.setBorder(new TitledBorder("在线用户"));
		//右边消息显示区面板部分
		rightscrollPanel = new JScrollPane(textArea);
		rightscrollPanel.setBorder(new TitledBorder("消息显示区"));
		
		//分割中间部分面板
		centerSplit =new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftscrollPanel,rightscrollPanel);
		centerSplit.setSize(811, 314);
		centerSplit.setLocation(0, 72);
		centerSplit.setDividerLocation(100); //设置分割的位置为从左向右100
		
		//底部(南)面板界面
		southPanel = new JPanel(new BorderLayout());
		southPanel.setSize(811, 64);
		southPanel.setLocation(0, 387);
		southPanel.setBorder(new TitledBorder("写信息"));
		southPanel.add(inputbox,"Center"); //信息输入位置
		southPanel.add(btn_send,"East"); //发送按钮
		
		frame = new JFrame("客户端");
//		frame.getContentPane().setLayout(new BorderLayout());
		frame.getContentPane().setLayout(null);
		frame.getContentPane().add(northPanel,"North");
		frame.getContentPane().add(centerSplit,"Center");
		frame.getContentPane().add(southPanel,"South");
		frame.setSize(840,500);
		int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
		int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
		frame.setLocation((screen_width-frame.getWidth())/2,(screen_height-frame.getWidth())/2);
		frame.setVisible(true); //设置可见
		
		frame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent arg0) {
				if(isConnect) {
					String info_send = "OFFLINE@"+"我下线了";																	
					write.println(info_send);将信息写进字符缓冲区
					write.flush();//刷新该流的缓冲
					isConnect = false;
					
				}
			}
		});
	}
	
	
	public static void main(String[] args) {

			EventQueue.invokeLater(new Runnable() {
				public void run() {
					try {
						ClientSide frame = new ClientSide();
						frame.setVisible(true);
						
					} catch (Exception e) {
						e.printStackTrace();
				}
				}
			});
		
	}

//接收客户端
	public class Accept extends Thread{
		private Socket socket;
		public Accept( Socket socket) {
			this.socket = socket;
		}
		public void run() {
			try {
				
//				打开客户端输入流
				in = socket.getInputStream();
				buf = new BufferedReader(new InputStreamReader(in));//字符输入流
				while(true) {
					if(!isConnect) {
						return;
					}
					String info_accept = buf.readLine();
					StringTokenizer str = new StringTokenizer(info_accept,"@");//分割接收的信息,提取命令 
					String order = str.nextToken();//命令
					String send_massage = str.nextToken();
					
					//消息种类分类
					switch(order) {
					//将新上线的用户打印到在线人数区。
					case "NEWCLIENT":
						listModel.addElement(send_massage);
						break;
					//将接收的消息打印到客户的消息显示区
					case "SEND_MESSAGE":
						textArea.append(send_massage+"\n");
						break;
					//弹出服务器发送的警告
					case "WARNING":
						textArea.append(send_massage+"\n");
						JOptionPane.showMessageDialog(null,send_massage, name, JOptionPane.INFORMATION_MESSAGE);
						break;
					//接收其它用户下线信息,并更新在线人数列表
					case "OFFLINE":
						listModel.removeElement(send_massage);
						textArea.append("服务器:"+send_massage+"已下线\n");
//						btn_disconnect.setEnabled(false);
						break;
					//将接收的私聊消息打印到客户的消息显示区
					case " ":
						textArea.append(send_massage+"\n");
						break;
					//被踢用户显示被踢消息
					case "Kick":
						isConnect = false;
						inputbox_ip.setEditable(true);
						inputbox_port.setEditable(true);
						inputbox_username.setEditable(true);
						listModel.clear();
						textArea.append("服务器:您已被踢出群聊\n");
						write.close();
						buf.close();
						out.close();
						in.close();
						break;																					
					}
				}				
			} catch (IOException e) {

				e.printStackTrace();
			}
		}
	}
}

    

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值