⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qq.java

📁 一个用纯java语言 写的 QQ 客户 端
💻 JAVA
字号:
/**
 * QQ聊天室客户端
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.awt.geom.*;

public class Qq {
	/**
	 * 主方法:启动登陆线程
	 */
	public static void main(String[] args) throws Exception {
		Thread login = new LoginThread();
		login.start();
	}
}

/**
 * 登陆线程
 */
class LoginThread extends Thread implements Protocol {
	private JFrame loginf;

	private JTextField t;

	public void run() {
		/*
		 * 设置登陆界面
		 */
		loginf = new JFrame();
		loginf.setSize(400, 150);
		loginf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		loginf.setTitle(SOFTWARE + " - 登陆");

		t = new JTextField("Version " + VERSION + "        By Lindan");
		t.setHorizontalAlignment(JTextField.CENTER);
		t.setEditable(false);
		loginf.getContentPane().add(t, BorderLayout.SOUTH);

		JPanel loginp = new JPanel(new GridLayout(3, 2));
		loginf.getContentPane().add(loginp);

		JTextField t1 = new JTextField("登陆名:");
		t1.setHorizontalAlignment(JTextField.CENTER);
		t1.setEditable(false);
		loginp.add(t1);

		final JTextField loginname = new JTextField("");
		loginname.setHorizontalAlignment(JTextField.CENTER);
		loginp.add(loginname);

		JTextField t2 = new JTextField("服务器IP:");
		t2.setHorizontalAlignment(JTextField.CENTER);
		t2.setEditable(false);
		loginp.add(t2);

		final JTextField loginIP = new JTextField(DEFAULT_IP);
		loginIP.setHorizontalAlignment(JTextField.CENTER);
		loginp.add(loginIP);

		/*
		 * 监听退出按钮(匿名内部类)
		 */
		JButton b1 = new JButton("退  出");
		loginp.add(b1);
		b1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});

		final JButton b2 = new JButton("登  陆");
		loginp.add(b2);

		loginf.setVisible(true);

		/**
		 * 监听器,监听"登陆"Button的点击和TextField的回车
		 */
		class ButtonListener implements ActionListener {
			private Socket s;

			public void actionPerformed(ActionEvent e) {
				if (checkName(loginname.getText())) {
					try {
						s = new Socket(loginIP.getText(), Integer
								.parseInt(DEFAULT_PORT));
						/*
						 * 连接服务器
						 */
						try {
							InputStream is = s.getInputStream();
							InputStreamReader ir = new InputStreamReader(is,
									"GBK");
							BufferedReader in = new BufferedReader(ir);
							OutputStream os = s.getOutputStream();
							OutputStreamWriter or = new OutputStreamWriter(os,
									"GBK");
							PrintWriter out = new PrintWriter(or);
							out.println(VERSION);
							out.flush();
							out.println(loginname.getText());
							out.flush();
							String ver;
							if (!(ver = in.readLine()).equals(VERSION)) {
								throw new VersionException(ver);
							}
							if (in.readLine().equals(USER_EXIST)) {
								throw new ExistException();
							}
							/*
							 * 启动聊天线程
							 */
							Thread chat = new ChatThread(loginname.getText(),
									s, in, out);
							loginf.setVisible(false);
							loginf.setEnabled(false);
							chat.start();
						} catch (IOException e1) {// 流操作异常
							t.setText("通讯失败,请重试!");
							try {
								s.close();
							} catch (IOException e2) {
							}
						} catch (VersionException e3) {// 用户存在异常(接口中定义)
							t.setText(e3.getMessage());
							try {
								s.close();
							} catch (IOException e4) {
							}
						} catch (ExistException e5) {// 用户存在异常(接口中定义)
							t.setText(e5.getMessage());
							try {
								s.close();
							} catch (IOException e6) {
							}
						}
					} catch (IOException e7) {// Socket连接服务器异常
						t.setText("连接服务器失败,请重试!");
					}
				}
			}
		}
		ButtonListener bl = new ButtonListener();
		b2.addActionListener(bl);
		loginname.addActionListener(bl);
		loginIP.addActionListener(bl);
	}

	/**
	 * 判断登陆名是否有效
	 */
	private boolean checkName(String name) {
		if (name.length() < NAME_MIN) {
			t.setText("错误:登陆名不能小于" + NAME_MIN + "字符");
			return false;
		}
		if (name.length() > NAME_MAX) {
			t.setText("错误:登陆名不能大于" + NAME_MAX + "字符");
			return false;
		}
		if (name.indexOf(" ") > -1) {
			t.setText("错误:登陆名不能包含空格");
			return false;
		}
		for (int i = 0; i < FORBID_WORDS.length; i++) {
			if (name.indexOf(FORBID_WORDS[i]) > -1) {
				t.setText("错误:登陆名不能包含敏感信息");
				return false;
			}
		}
		return true;
	}
}

/**
 * 聊天线程
 */
class ChatThread extends Thread implements Protocol {
	private Map users = new HashMap();

	private String name;

	private Socket s;

	private BufferedReader in;

	private PrintWriter out;

	private JComboBox cb;

	private JFrame f;

	private JTextArea ta;

	private JTextField tf;

	private static long time;// 上一条信息的发出时间

	private static int total;// 在线人数统计

	public ChatThread(String name, Socket s, BufferedReader in, PrintWriter out) {
		this.name = name;
		this.s = s;
		this.in = in;
		this.out = out;
	}

	public static BounceFrame hyn = new BounceFrame();

	public static BounceFrame hye = new BounceFrame();

	public static BounceFrame hyw = new BounceFrame();

	void runt() {
		hyw.addBall();
		hye.addBall();
		hyn.addBall();
		BounceFrame.counter++;
	}

	public void run() {
		/*
		 * 设置聊天室窗口界面
		 */
		f = new JFrame();
		f.setSize(600, 400);
		f.setTitle(SOFTWARE + " - " + name + "     当前在线人数:" + ++total);
		f.setLocation(300, 200);
		ta = new JTextArea();
		JScrollPane sp = new JScrollPane(ta);
		ta.setEditable(false);
		tf = new JTextField();
		cb = new JComboBox();
		cb.addItem("All");
		JPanel pl = new JPanel(new BorderLayout());
		pl.add(cb);
		JPanel p = new JPanel(new BorderLayout());
		p.add(pl, BorderLayout.WEST);
		p.add(tf);
		f.getContentPane().add(p, BorderLayout.SOUTH);
		f.getContentPane().add(sp);
		f.getContentPane().add(BounceFrame.canvas, BorderLayout.NORTH);
		/**
		 * 监听关闭按钮
		 */
		class MyWindowListener implements WindowListener {
			public void windowActivated(WindowEvent e) {
			}

			public void windowClosed(WindowEvent e) {
			}

			public void windowClosing(WindowEvent e) {
				/*
				 * 向服务器发送退出信息
				 */
				out.println(SYSTEM_MSG + USER_LOGOUT);
				out.flush();
				try {
					s.close();
				} catch (IOException e1) {
				}
				System.exit(0);
			}

			public void windowDeactivated(WindowEvent e) {
			}

			public void windowDeiconified(WindowEvent e) {
			}

			public void windowIconified(WindowEvent e) {
			}

			public void windowOpened(WindowEvent e) {
			}
		}
		MyWindowListener wl = new MyWindowListener();
		f.addWindowListener(wl);

		/**
		 * 接收服务器发送的信息
		 */
		class GetMsgThread extends Thread {
			public void run() {
				try {
					String msg, name;
					while (!s.isClosed()) {
						/*
						 * 不断接受服务器信息,外层循环防止读到null跳出循环
						 */
						while (!s.isClosed() && (msg = in.readLine()) != null) {
							msg = specialMsg(msg);// 系统信息处理
							if (msg.startsWith(MSG_FROM)) {
								msg = msg.replaceFirst(MSG_FROM, "");
								name = msg.substring(0, msg.indexOf(NAME_END));
								msg = msg.replaceFirst(name + NAME_END, "");
								ta.append(name + " 悄悄地对你说: " + msg + "\n");
							} else if (msg.contains(NAME_END)) {
								name = msg.substring(0, msg.indexOf(NAME_END));
								msg = msg.replaceFirst(name + NAME_END, "");
								ta.append(name + " 说: " + msg + "\n");// 在窗口显示信息
							} else {
								ta.append(msg + "\n");
							}
							ta.setCaretPosition(ta.getText().length());
						}
					}
				} catch (Exception e) {
					out.println(SYSTEM_MSG + USER_LOGOUT);// 当异常产生时向系统发出退出信息
				} finally {
					try {
						s.close();
					} catch (IOException e) {
					}
				}
			}
		}
		GetMsgThread gt = new GetMsgThread();
		gt.start();

		/*
		 * 监听用户在窗口输入的信息(匿名内部类)
		 */
		tf.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String msg = e.getActionCommand();
				if (isAllowed(msg, null)) {
					sendMsg((String) cb.getSelectedItem(), msg, true);
					tf.setText(null);
					runt();
				}
			}
		});

		f.setVisible(true);
	}

	/**
	 * 处理系统信息
	 */
	private String specialMsg(String msg) {
		if (msg.startsWith(SYSTEM_MSG)) {
			msg = msg.replaceFirst(SYSTEM_MSG, "");
			/*
			 * 当有人进入聊天室
			 */
			if (msg.startsWith(ADD_USER)) {
				msg = msg.replaceFirst(ADD_USER, "");
				cb.addItem(msg);
				// users.put(msg, new ChatWindow(msg));
				total++;
				msg += " 进入聊天室";
			}
			/*
			 * 当有人离开聊天室
			 */
			else if (msg.startsWith(DELETE_USER)) {
				msg = msg.replaceFirst(DELETE_USER, "");
				cb.removeItem(msg);
				// ((ChatWindow) users.get(msg)).tas.append(msg + " 退出聊天室\n");
				users.remove(msg);
				total--;
				msg += " 退出聊天室";
			}
			/*
			 * 登陆时获得的在线用户列表信息
			 */
			else if (msg.startsWith(EXIST_USERS)) {
				msg = msg.replaceFirst(EXIST_USERS, "");
				cb.addItem(msg);
				// users.put(msg, new ChatWindow(msg));
				total++;
				msg += " 正在聊天室";
			}
			/*
			 * 即时显示在线人数
			 */
			f.setTitle(SOFTWARE + " - " + name + "     当前在线人数:" + total);
			return msg;
		}
		return msg;
	}

	/**
	 * 检查信息是否允许发送,包括检查敏感词汇/空信息/刷屏
	 */
	private boolean isAllowed(String msg, String msgto) {
		/*
		 * 过滤空信息
		 */
		if (msg.length() == 0)
			return false;
		String errmsg = null;
		/*
		 * 过滤敏感词汇
		 */
		for (int i = 0; i < FORBID_WORDS.length; i++) {
			if (msg.indexOf(FORBID_WORDS[i]) > -1) {
				errmsg = "包含敏感信息,信息发送失败!\n";
				break;
			}
		}
		long timenow = (new Date()).getTime();// 获得当前时间信息
		/*
		 * 防刷屏
		 */
		if (timenow - time < TIME_BETWEEN_MSG * 1000) {
			errmsg = "发送信息的最短间隔为" + TIME_BETWEEN_MSG + "秒,请勿刷屏!\n";
		}
		if (errmsg == null) {
			time = timenow;// 记录发送信息时间
			return true;
		} else if (msgto == null)
			ta.append(errmsg);

		return false;
	}

	private void sendMsg(String name1, String msg, boolean isRoomShow) {
		out.println(name1 + NAME_END + msg);
		out.flush();
		if (name1.equals("All"))
			ta.append("我 说: " + msg + "\n");
		else {
			if (isRoomShow)
				ta.append("我悄悄地对 " + name1 + " 说: " + msg + "\n");
		}
	}
}

/** 显示的物体 */
class Ball {
	public int n = 0;

	public Ball(Component c) {
		canvas = c;
	}

	public Ball(Component c, Color color) {
		canvas = c;
		this.color = color;
	}

	/** 选择移动的物体 */
	public void draw(Graphics2D g2) {
		if (color != null)
			g2.setColor(color);

		int n = BounceFrame.counter % 4;
		s = BounceFrame.counter % 3;
		if (n == 0)
			g2.drawString(ch[s], x + 8, y + 8);
		if (n == 2)
			g2.drawLine(x, y, x + 10, y + 10);
		if (n == 3)
			g2.fill3DRect(x, y, XSIZE, YSIZE, raised);
		if (n == 1)
			g2.fill(new Ellipse2D.Double(x, y, XSIZE, YSIZE));
	}

	/** 控制移动 */
	public void move() {
		if (x + XSIZE >= canvas.getWidth() && y + YSIZE >= canvas.getHeight()) {
			y -= dy;
			n = 1;
			canvas.repaint();
			return;
		}
		if (x + XSIZE >= canvas.getWidth() && y + YSIZE < canvas.getHeight()) {

			if (n == 1) {
				if (y == 12) {
					x -= dx;

				}
				y -= dy;
			}
			canvas.repaint();
			return;
		}
		if (x + XSIZE < canvas.getWidth() && y + YSIZE >= canvas.getHeight()) {
			x += dx;
			canvas.repaint();
			return;
		}
		if (x + XSIZE < canvas.getWidth() && y + YSIZE < canvas.getHeight()) {
			if (n == 0)
				y += dy;
			if (n == 1)
				x -= dx;
			canvas.repaint();
			return;
		}

	}

	private Component canvas;

	private Color color;

	private static final int XSIZE = 10;

	private static final int YSIZE = 10;

	private static final boolean raised = true;

	private int x = 0;

	private int y = 0;

	private int dx = 2;

	private int dy = 2;

	String[] ch = { "郭", "志", "勇" };

	public static int s = 2;
}

/** 显示移动物体的线程 */
class BallThread extends Thread {

	public BallThread(Ball aBall) {
		b = aBall;
	}

	public void run() {

		try {

			for (int i = 1; i <= 696; i++) {
				b.move();
				sleep(10);
			}
		} catch (InterruptedException iex) {
			iex.printStackTrace();
		}
	}

	private Ball b;

}

/** 生成2D图行 */
class BallCanvas extends JPanel {

	public void add(Ball b) {
		balls.add(b);
	}

	public void paintComponent(Graphics g) {

		super.paintComponent(g);

		Graphics2D g2 = (Graphics2D) g;

		for (int i = 0; i < balls.size(); i++) {
			Ball b = (Ball) balls.get(i);
			b.draw(g2);
		}

	}

	private ArrayList balls = new ArrayList();

}

/** 显示窗口 */
class BounceFrame extends JPanel {

	/** 产生的动作 */
	public void addBall() {
		Ball b = new Ball(canvas, colors[counter % colors.length]);
		canvas.add(b);
		BallThread thread = new BallThread(b);
		thread.start();
	}

	public static BallCanvas canvas = new BallCanvas();

	public static final int WIDTH = 450;

	public static final int HEIGHT = 350;

	private Color[] colors = { Color.blue, Color.magenta, Color.green,
			Color.orange, Color.red, Color.yellow, Color.pink };

	public static int counter = 0;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -