实现了一个简单的聊天软件,但是有个BUG,一直没有想通问题出在哪里。

//登陆界面
package com.konghao.netGUI05;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.*;

@SuppressWarnings("serial")
public class LoginFrame extends JFrame {
	private JButton jb; //登陆按钮
	private JTextField jtf;//输入框
	private JLabel jl;//"用户名"
	public static void main(String[] args) {
		new LoginFrame();
	}
	//界面关闭方法
	public void close(){
		this.setVisible(false);
	}
	public LoginFrame() {
		this.setSize(350,100);
		this.setLocation(500, 500);
		this.setResizable(false);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setTitle("登陆");
		
		jb = new JButton("登陆");
		jtf = new JTextField(12);
		jl = new JLabel("请输入用户名:");
		jtf.addKeyListener(new KeyClick());
		
		this.add(jl);this.add(jtf);this.add(jb);
		this.setLayout(new FlowLayout());
		//添加事件
		jb.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				String name = jtf.getText();
				if(name==null||name.trim().equals("")){
					JOptionPane.showMessageDialog(null, "用户名不能为空!");
					return;
				}
				new ClientFrame(name);
				close();
			}
		});
		
		
		this.setVisible(true);
		
	}
	
	private class KeyClick extends KeyAdapter{
		@Override
		public void keyPressed(KeyEvent e) {
			if(e.getKeyCode()==KeyEvent.VK_ENTER){
				String name = jtf.getText();
				if(name==null||name.trim().equals("")){
					JOptionPane.showMessageDialog(null, "用户名不能为空!");
					return;
				}
				new ClientFrame(name);
				close();
			}
		}
	}
}

//客户端


package com.konghao.netGUI05;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.*;

import javax.swing.DefaultListModel;
import javax.swing.*;



@SuppressWarnings("serial")
public class ClientFrame extends JFrame{
//	public static void main(String[] args) {
//		new ClientFrame();
//	}
	private JTextArea jta; //中央信息区域
	private JList<String>  list; //当前用户列表
	private JScrollPane jsp1,jsp2; //滚动条
	private JPanel jp;//底部容器
	private JTextField jtf;//信息输入框
	private JButton jb;//发送按钮
	private JLabel jl;
	private String name;
	private boolean stop = false;
	
	
	private Socket s;
	private PrintWriter out;
	private BufferedReader br;
	private DefaultListModel<String> model ;
	private List<String> users_selected = null;
	
	public ClientFrame(String name) {
		this.name = name;
		this.setTitle("局域网聊天:"+name);
		this.setSize(600,500);
		this.setLocation(300, 300);
		this.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				out.println(Server.DISCONNECT_TOKEN);
			}
			
		});
		
		jta = new JTextArea();
		jsp1 = new JScrollPane(jta);
		list = new JList<String>();
		list.setBackground(Color.GREEN);
		jsp2 = new JScrollPane(list);
		
		model = new DefaultListModel<String>();
		list.setModel(model);
		
		jp = new JPanel();
		jtf = new JTextField(18);
		jb = new JButton("发送");
		jl = new JLabel("请输入消息:");
		list.setFixedCellWidth(100);
		new BorderLayout();
		this.add(jsp2,BorderLayout.WEST);
		this.add(jsp1);
		jp.add(jl);jp.add(jtf);jp.add(jb);
		new BorderLayout();
		this.add(jp,BorderLayout.SOUTH);
		jb.addActionListener(new BottonClick());
		jtf.addKeyListener(new KeyPressed());
		
		connect();
		
		this.setVisible(true);
		
	}
	
	//连接方法
	public void connect() {
			try {
				s = new Socket(Server.HOST,Server.PORT);
				br = new BufferedReader(new InputStreamReader(s.getInputStream()));
				out = new PrintWriter(s.getOutputStream(),true);
				out.println(name);
				
				new Thread(new ReceiveThread()).start();
				
			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
	}
	
	//接收服务器信息线程
	public class ReceiveThread implements Runnable{

		@Override
		public void run() {
			try {
				while(true){
					if(stop){
						break;
					}
					receive();
				}
				
				System.exit(0);
			} catch (IOException e) {
				e.printStackTrace();
			} finally{
				try {
					if(s!=null) s.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
		}
		
	}
	//接收方法
	public void receive() throws IOException{
		String str = br.readLine();
		if(Server.DISCONNECT_TOKEN.equals(str)){
			close();
			return;
		}
		if(str.startsWith(Server.USER_FLAG)){
			addList(str);
			return;
		}
		
		addArea(str); //将接收到的信息添加到信息区
	}
	//点击用户列表时获得用户;
	public String getUsers(){
		users_selected = new ArrayList<String>();
		users_selected = list.getSelectedValuesList();
		String str = Server.TOKEN_START;
		if(!users_selected.isEmpty()){
			for(String users:users_selected){
				if(users.equals("所有人")){
					users_selected.remove(users);
					return str+Server.TOKEN_ALL+Server.TOKEN_END;
				}else{
					str+=(users+","); // to: XXX,XXX,XX,:endmsg;
				}
			}
		}else{
			str+=Server.TOKEN_ALL;
		}
		return str+Server.TOKEN_END;
		
	}
	//将用户列表添加到List的方法
	public void addList(String str){
		model.removeAllElements();
		String us = str.substring(Server.USER_FLAG.length());
		String[] usr = us.split(",");
		model.addElement("所有人");
		for(String u : usr){
			model.addElement(u);
		}
	}
	//将信息添加到TextArea的方法
	public void addArea(String msg){
		jta.setText(jta.getText()+msg+"\n");
	}
	
	//关闭方法
	public void close(){
		stop = true;
	}
	//给服务器发送信息方法
	public void send(){
		String msg = jtf.getText();
		if(msg==null||msg.trim().equals("")){
			jtf.setText("");
			return;
		}
		out.println(getUsers()+msg);
		jtf.setText("");
		
	}
	//点击按钮事件
	private class BottonClick  implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent e) {
			if(e.getSource()==jb){
				send();
			}
		}
	}
	//点击回车键事件
	private class KeyPressed extends KeyAdapter{
		@Override
		public void keyPressed(KeyEvent e) {
			if(e.getKeyCode()==KeyEvent.VK_ENTER){
				send();
			}
		}
	}
	
	
}
//服务端

package com.konghao.netGUI05;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Server {
	public static final String HOST = "127.0.0.1";
	public static final int PORT = 6060;
	public static final String DISCONNECT_TOKEN = "disconnect";
	public static final String USER_FLAG = "users:";
	public static final String TOKEN_START = "to:";
	public static final String TOKEN_END = ":end";
	public static final String TOKEN_ALL = "allOfClients";
	
	private boolean stop = false;
	private Map<String,ServerThread> clients;
	
	
	public static void main(String[] args) {
		new Server().startup();
	}
	
	public void startup(){
		ServerSocket ss = null;
		clients = new HashMap<String,ServerThread>(); //初始化不能放在while循环之中,否则每次添加都是一个
												//新的列表。
		try {
			ss = new ServerSocket(PORT);
			System.out.println("The Server is ready!");
			while(true){
				Socket s = ss.accept();
				ServerThread st = new ServerThread(s);
				new Thread(st).start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(ss!=null) ss.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public class ServerThread implements Runnable{
		private Socket s;
		private BufferedReader br = null;
		private PrintWriter out = null;
		private String name;
		
		public ServerThread(Socket s) throws IOException {
			this.s = s;
			br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			out = new PrintWriter(s.getOutputStream(),true);
			name = br.readLine()+"["+s.getInetAddress().getHostAddress()+"]";
			clients.put(name,this);
			send( "--------[系统消息:"+name+"上线了!]----------");
			sendUsers(); // 将用户列表传给客户端
		}
		//从信息中分离出用户信息
		public String[] getUsers_selected(String msg){
			String str = msg.substring(TOKEN_START.length(), msg.indexOf(TOKEN_END));
			String[] us = str.split(",");
			return us;
		}
		//从信息中分离出消息
		public String format(String msg){
			String str = msg.substring(msg.indexOf(TOKEN_END)+TOKEN_END.length());
			return str;
		}
		
		//给客户端反馈信息
		public void send(String msg){
			Set<String> keys = clients.keySet();
			boolean isAll =false;
			if(msg.startsWith(TOKEN_START)){
				String msg2 = format(msg); //分离出的消息
				String[] uss = getUsers_selected(msg); //分离出的用户
				for(String u : uss){
					if(u.equals(TOKEN_ALL)){
						isAll = true;
					}
				}
				if(isAll){
					for (String st : keys) {
						clients.get(st).out.println(name+":"+msg2+"[公]");
					}
				}else{
					for(String u : uss){
						clients.get(u).out.println(name+":"+msg2+"[私]");
					}
				}
			}else{
				for (String st : keys) {
					clients.get(st).out.println(msg);
				}
				
			}
		}
		//给客户端发送用户信息
		public void sendUsers(){
			String us = USER_FLAG;
			Set<String> keys = clients.keySet();
			for (String st : keys) {
				us+=(st+",");
			}
			
			send(us);
		}


		@Override
		public void run() {
			
			try {
				while(true){
					if(stop){ 
						break;
					}
					String str = br.readLine();
					if(DISCONNECT_TOKEN.equals(str)){
						stop();
						break;
					}
					send(str);
					//System.out.println(name+":"+str);
				}
			} catch (SocketException e){
				stop();
			} catch (IOException e) {
				e.printStackTrace();
			} finally{
				try {
					if(s!=null) s.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
		}
		
		//停止方法
		public void stop(){
			stop = true;
			out.println(DISCONNECT_TOKEN);
			clients.remove(name);
			sendUsers();
			send("--------[系统消息:"+name+"已经退出!]---------");
		}
		
	}
	
	
	
}

BUG:  每次打开多个客户端后再关闭其中一个,就会遇到。


BUG解决办法:


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值