频道栏目
首页 > 资讯 > Java > 正文

Java多线程实现的聊天客户端和服务器

16-10-17        来源:[db:作者]  
收藏   我要投稿

主要涉及

·Java中GUI程序的编写,包括事件监听机制。

·Java的网络通信编程,ServerSocket,Socket类的使用。

·Java中多线程的编程,Thread类,Runnable接口的使用。

源代码

客户端

package project1;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

import javax.swing.*;

public class Client {
	private JFrame clientFrame;
	private JLabel IPLabel;
	private JLabel PortLabel;
	private JLabel sayLabel;
	private JLabel nicknameLabel;
	private JTextField IPText;
	private JTextField PortText;
	private JTextField nicknameText;
	private JTextField sayText;
	private JButton connectButton;
	private JButton nicknameButton;
	private JButton sayButton;
	private JPanel jPanelNorth;
	private JPanel jPanelSouth0;
	private JPanel jPanelSouth1;
	private JPanel jPanelSouth2;
	private JTextArea clientTextArea;
	private JScrollPane scroller;
	private BufferedReader reader;
	private PrintWriter writer;
	private String nickname;

	public static void main(String args[]) {
		Client aClient = new Client();
		aClient.startUp();
	}

	// 初始化组件
	public Client() {
		nickname = "客户端";

		clientFrame = new JFrame();
		jPanelNorth = new JPanel();
		IPLabel = new JLabel("服务器IP", JLabel.LEFT);
		IPText = new JTextField(10);
		PortLabel = new JLabel("服务器端口", JLabel.LEFT);
		PortText = new JTextField(10);
		connectButton = new JButton("连接");
		clientTextArea = new JTextArea();
		scroller = new JScrollPane(clientTextArea);
		jPanelSouth0 = new JPanel();
		jPanelSouth1 = new JPanel();
		jPanelSouth2 = new JPanel();
		nicknameLabel = new JLabel("昵称", JLabel.LEFT);
		nicknameText = new JTextField(nickname, 30);
		nicknameButton = new JButton("确认");
		sayLabel = new JLabel("消息", JLabel.LEFT);
		sayText = new JTextField(30);
		sayButton = new JButton("确认");
	}

	// 构建GUI
	private void buildGUI() {
		// 窗口的设置
		clientFrame.setTitle("客户端");
		clientFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		clientFrame.setSize(550, 550);

		// 北区的组件
		jPanelNorth.add(IPLabel);
		jPanelNorth.add(IPText);
		jPanelNorth.add(PortLabel);
		jPanelNorth.add(PortText);
		jPanelNorth.add(connectButton);
		clientFrame.getContentPane().add(BorderLayout.NORTH, jPanelNorth);

		// 中间的组件
		clientTextArea.setFocusable(false);
		scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		clientFrame.getContentPane().add(BorderLayout.CENTER, scroller);

		// 南区的组件
		jPanelSouth1.add(nicknameLabel);
		jPanelSouth1.add(nicknameText);
		jPanelSouth1.add(nicknameButton);
		jPanelSouth2.add(sayLabel);
		jPanelSouth2.add(sayText);
		jPanelSouth2.add(sayButton);
		jPanelSouth0.setLayout(new BoxLayout(jPanelSouth0, BoxLayout.Y_AXIS));
		jPanelSouth0.add(jPanelSouth1);
		jPanelSouth0.add(jPanelSouth2);
		clientFrame.getContentPane().add(BorderLayout.SOUTH, jPanelSouth0);

		// 设置窗口可见
		clientFrame.setVisible(true);
	}

	// 客户端运行
	public void startUp() {
		buildGUI();

		// 接收服务器消息的线程
		Runnable incomingReader = new Runnable() {
			@Override
			public void run() {
				String message;
				try {
					while ((message = reader.readLine()) != null) {
						clientTextArea.append(message + "\n");
					}
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		};

		// 监听Connect按钮,实现服务器的连接
		connectButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String aServerIP = IPText.getText();
				String aServerPort = PortText.getText();

				if (aServerIP.equals("") || aServerPort.equals("")) {
					JOptionPane.showMessageDialog(clientFrame, "请输入 完整的 IP和端口!");
				} else {
					try {
						@SuppressWarnings("resource")
						Socket clientSocket = new Socket(aServerIP, Integer.parseInt(aServerPort));
						InputStreamReader streamReader = new InputStreamReader(clientSocket.getInputStream());
						reader = new BufferedReader(streamReader);
						writer = new PrintWriter(clientSocket.getOutputStream());

						clientTextArea.append("服务器已连接...\n");

						Thread readerThread = new Thread(incomingReader);
						readerThread.start();
					} catch (Exception ex) {
						JOptionPane.showMessageDialog(clientFrame, "连接不上服务器!\n请确认 IP 和 端口 输入正确。");
					}
				}
			}
		});

		// 监听nickname,设置昵称
		ActionListener nicknameListener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String aText = nicknameText.getText();
				if (!aText.equals("")) {
					nickname = aText;
				}
			}
		};
		nicknameButton.addActionListener(nicknameListener);
		nicknameText.addActionListener(nicknameListener);
		nicknameText.addFocusListener(new FocusListener() {
			@Override
			public void focusGained(FocusEvent e) {
			}

			@Override
			public void focusLost(FocusEvent e) {
				String aText = nicknameText.getText();
				if (!aText.equals("")) {
					nickname = aText;
				}
			}
		});

		// 发送消息到服务器
		ActionListener SayListener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String aText = sayText.getText();
				if (aText.equals("")) {
					JOptionPane.showMessageDialog(clientFrame, "内容不能为空!");
				} else {
					try {
						writer.println(nickname + ":" + aText);
						writer.flush();
					} catch (Exception ex) {
						ex.printStackTrace();
					}
					sayText.setText("");
				}
			}
		};
		sayButton.addActionListener(SayListener);
		sayText.addActionListener(SayListener);

	}

}

服务器

package project1;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.*;

public class Server {
	private JFrame serverFrame;
	private JLabel portLabel;
	private JLabel sayLabel;
	private JLabel nicknameLabel;
	private JTextField portText;
	private JTextField sayText;
	private JTextField nicknameText;
	private JButton startButton;
	private JButton sayButton;
	private JButton nicknameButton;
	private JPanel jPanelNorth;
	private JPanel jPanelSouth0;
	private JPanel jPanelSouth1;
	private JPanel jPanelSouth2;
	private JScrollPane scroller;
	private JTextArea serverTextArea;
	private ArrayList clientOutputStreams;
	private String nickname;

	public static void main(String[] args) {
		Server aServer = new Server();
		aServer.startUp();
	}

	// 初始化组件
	public Server() {
		nickname = "服务器";

		serverFrame = new JFrame();
		jPanelNorth = new JPanel();
		portLabel = new JLabel("端口", JLabel.LEFT);
		portText = new JTextField(30);
		startButton = new JButton("开始");
		serverTextArea = new JTextArea();
		scroller = new JScrollPane(serverTextArea);
		nicknameLabel = new JLabel("昵称", JLabel.LEFT);
		nicknameText = new JTextField(nickname, 30);
		nicknameButton = new JButton("确认");
		jPanelSouth0 = new JPanel();
		jPanelSouth1 = new JPanel();
		jPanelSouth2 = new JPanel();
		sayLabel = new JLabel("消息", JLabel.LEFT);
		sayText = new JTextField(30);
		sayButton = new JButton("确认");
	}

	// 构建GUI
	private void buildGUI() {
		// 窗口的设置
		serverFrame.setTitle("服务器");
		serverFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		serverFrame.setSize(550, 550);

		// 北区的组件
		jPanelNorth.add(portLabel);
		jPanelNorth.add(portText);
		jPanelNorth.add(startButton);
		serverFrame.getContentPane().add(BorderLayout.NORTH, jPanelNorth);

		// 中间的组件
		serverTextArea.setFocusable(false);
		scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		serverFrame.getContentPane().add(BorderLayout.CENTER, scroller);

		// 南区的组件
		jPanelSouth1.add(nicknameLabel);
		jPanelSouth1.add(nicknameText);
		jPanelSouth1.add(nicknameButton);
		jPanelSouth2.add(sayLabel);
		jPanelSouth2.add(sayText);
		jPanelSouth2.add(sayButton);
		jPanelSouth0.setLayout(new BoxLayout(jPanelSouth0, BoxLayout.Y_AXIS));
		jPanelSouth0.add(jPanelSouth1);
		jPanelSouth0.add(jPanelSouth2);
		serverFrame.getContentPane().add(BorderLayout.SOUTH, jPanelSouth0);

		// 设置窗口可见
		serverFrame.setVisible(true);
	}

	// 服务器运行
	public void startUp() {
		buildGUI();

		// 监听Start按钮,建立端口
		ActionListener startListener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				clientOutputStreams = new ArrayList();
				String aPort = portText.getText();

				if (aPort.equals("")) {
					JOptionPane.showMessageDialog(serverFrame, "请输入正确的端口号!");
				} else {
					try {
						// 等待客户端连接的线程
						Runnable serverRunnable = new Runnable() {
							@Override
							public void run() {
								ServerSocket serverSocket;
								try {
									serverSocket = new ServerSocket(Integer.parseInt(aPort));
									serverTextArea.append("正在等待客户端连接...\n");
									while (true) {
										Socket clientSocket = serverSocket.accept();
										serverTextArea.append("客户端已连接...\n");

										PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
										clientOutputStreams.add(writer);

										Thread t = new Thread(new ClientHandler(clientSocket));
										t.start();
									}
								} catch (NumberFormatException | IOException e) {
									e.printStackTrace();
								}
							}
						};
						Thread serverThread = new Thread(serverRunnable);
						serverThread.start();
					} catch (Exception ex) {
						ex.printStackTrace();
					}
				}
			}
		};
		startButton.addActionListener(startListener);
		portText.addActionListener(startListener);

		// 监听nickname,设置昵称
		ActionListener nicknameListener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String aText = nicknameText.getText();
				if (!aText.equals("")) {
					nickname = aText;
				}
			}
		};
		nicknameButton.addActionListener(nicknameListener);
		nicknameText.addActionListener(nicknameListener);
		nicknameText.addFocusListener(new FocusListener() {
			@Override
			public void focusGained(FocusEvent e) {
			}

			@Override
			public void focusLost(FocusEvent e) {
				String aText = nicknameText.getText();
				if (!aText.equals("")) {
					nickname = aText;
				}
			}
		});

		// 监听Say按钮,发送消息
		ActionListener SayListener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String aText = sayText.getText();
				if (!aText.equals("")) {
					aText = nickname + ":" + aText;
					sendToEveryClient(aText);
					serverTextArea.append(aText + "\n");
					sayText.setText("");
				} else {
					JOptionPane.showMessageDialog(serverFrame, "内容不能为空!");
				}
			}
		};
		sayButton.addActionListener(SayListener);
		sayText.addActionListener(SayListener);
	}

	// 多客户端的线程
	public class ClientHandler implements Runnable {
		BufferedReader bReader;
		Socket aSocket;

		public ClientHandler(Socket clientSocket) {
			try {
				aSocket = clientSocket;
				InputStreamReader isReader = new InputStreamReader(aSocket.getInputStream());
				bReader = new BufferedReader(isReader);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}

		@Override
		public void run() {
			String message;
			try {
				while ((message = bReader.readLine()) != null) {
					sendToEveryClient(message);
					serverTextArea.append(message + "\n");
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	// 发送消息给所有客户端的方法
	private void sendToEveryClient(String message) {
		Iterator it = clientOutputStreams.iterator();
		while (it.hasNext()) {
			try {
				PrintWriter writer = (PrintWriter) it.next();
				writer.println(message);
				writer.flush();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

}

 

GUI运行截图

相关TAG标签
上一篇:细谈Slick(5):学习体会和实际应用
下一篇:MFC相关知识
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站