Java-项目-001-多人聊天带界面(界面利用可视化swt)

Java-项目-001-多人聊天带界面(界面利用可视化swt)-2020-6-25

零、操作效果

在这里插入图片描述

一、ClientApp.java


import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Text;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList; //用于存储客户信息
import java.util.StringTokenizer; //引入 StringTokenizer 类,用于信息分离
import java.net.*;
import java.io.*;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.List;

public class ClientApp {
	List clientsList;// 用户列表
	Socket socket = null;
	BufferedReader cin = null;
	PrintStream cout = null;
	String clientName = "";
	Label L1, L2, L3;
	Button connectServer, send, disconnect;
	// 连接服务器按钮、发送信息按钮、断开连接按钮
	Text ipAddress, textPort, textClientName, talkMessage, textAreaMessage;
	// IP地址输入框、端口输入框、用户名输入框、聊天信息输入框、聊天信息显示区
	protected Shell shell;

	/**
	 * Launch the application.
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			ClientApp window = new ClientApp();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window.
	 */
	public void open() {
		Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setSize(930, 550);
		shell.setText("简单聊天系统-客户端");
		// shell.setFont(SWTResourceManager.getFont("宋体", 14, SWT.NORMAL));

		L1 = new Label(shell, SWT.NONE);
		// L1.setFont(SWTResourceManager.getFont("宋体", 14, SWT.NORMAL));
		L1.setBounds(10, 15, 120, 40);
		L1.setText("服务器IP");

		L2 = new Label(shell, SWT.NONE);
		// L2.setFont(SWTResourceManager.getFont("宋体", 14, SWT.NORMAL));
		L2.setBounds(282, 15, 60, 40);
		L2.setText("端口");

		L3 = new Label(shell, SWT.NONE);
		// L3.setFont(SWTResourceManager.getFont("宋体", 14, SWT.NORMAL));
		L3.setBounds(471, 15, 120, 40);
		L3.setText("客户名称");

		ipAddress = new Text(shell, SWT.BORDER);
		// ipAddress.setFont(SWTResourceManager.getFont("宋体", 13, SWT.NORMAL));
		ipAddress.setText("127.0.0.1");
		ipAddress.setBounds(126, 14, 140, 40);

		textPort = new Text(shell, SWT.BORDER);
		// textPort.setFont(SWTResourceManager.getFont("宋体", 13, SWT.NORMAL));
		textPort.setText("4321");
		textPort.setBounds(345, 14, 120, 40);

		talkMessage = new Text(shell, SWT.BORDER);
		// talkMessage.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		// talkMessage.setFont(SWTResourceManager.getFont("宋体", 11, SWT.NORMAL));
		talkMessage.setText("");
		talkMessage.setBounds(10, 90, 484, 90);

		textAreaMessage = new Text(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
		textAreaMessage.setEditable(false);
		// textAreaMessage.setFont(SWTResourceManager.getFont("宋体", 11, SWT.NORMAL));
		// textAreaMessage.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		textAreaMessage.setBounds(282, 204, 616, 280);

		textClientName = new Text(shell, SWT.BORDER);
		// textClientName.setFont(SWTResourceManager.getFont("宋体", 13, SWT.NORMAL));
		textClientName.setBounds(597, 10, 110, 45);
		clientsList = new List(shell, SWT.BORDER);
		// clientsList.setFont(SWTResourceManager.getFont("宋体", 11, SWT.NORMAL));
		clientsList.setBounds(22, 204, 244, 280);
	
		
		connectServer = new Button(shell, SWT.NONE);
		// connectServer.setForeground(SWTResourceManager.getColor(SWT.COLOR_DARK_CYAN));
		// connectServer.setFont(SWTResourceManager.getFont("宋体", 14, SWT.NORMAL));
		connectServer.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				try {
					InetAddress ip = InetAddress.getByName(ipAddress.getText());
					int port = Integer.parseInt(textPort.getText());
					socket = new Socket(ip, port);
					textAreaMessage.append("系统提示:与聊天服务器系统开始连接......\n");
				} catch (IOException e1) {
					textAreaMessage.append("服务器端口打开出错\n");
				}
				if (socket != null) {
					textAreaMessage.append("系统提示:与服务器连接成功......\n");
					clientName = textClientName.getText().trim();
					try {
						cin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
						cout = new PrintStream(socket.getOutputStream());
						String str = "PEOPLE:" + clientName;
						cout.println(str);
						ReadMessageThread readThread = new ReadMessageThread();
						readThread.start();
					} catch (IOException e3) {
						textAreaMessage.append("输入输出异常\n");
					}
				}
			}
		});
		connectServer.setBounds(726, 15, 172, 40);
		connectServer.setText("连接服务器");
		send = new Button(shell, SWT.NONE);
		// send.setForeground(SWTResourceManager.getColor(SWT.COLOR_DARK_CYAN));
		// send.setFont(SWTResourceManager.getFont("宋体", 14, SWT.NORMAL));
		send.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				String str = talkMessage.getText();
				str = "MSG:" + clientName + ":" + str;
				cout.println(str);
			}
		});
		send.setBounds(500, 100, 200, 40);
		send.setText("发送信息");
		disconnect = new Button(shell, SWT.NONE);
		// disconnect.setForeground(SWTResourceManager.getColor(SWT.COLOR_DARK_CYAN));
		// disconnect.setFont(SWTResourceManager.getFont("宋体", 14, SWT.NORMAL));
		disconnect.setBounds(726, 100, 172, 40);
		disconnect.setText("\u65AD\u5F00\u8FDE\u63A5");
		disconnect.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				String str = "QUIT";
				cout.println(str);
				textAreaMessage.append("客户请求断开连接\n");
			}
		});

	}

	class ReadMessageThread extends Thread {
		boolean isRun = true;

		public void list(final ArrayList<String> imessage) {
			Display.getDefault().syncExec(new Runnable() {
				public void run() {
					clientsList.removeAll();
					for (String temp : imessage)
						clientsList.add(temp);
				}
			});
		}

		public void appendTextArea(String str) {
			final String str1 = str;
			Display.getDefault().syncExec(new Runnable() {
				public void run() {
					textAreaMessage.append(str1);
				}
			});
		}

		public void run() {
			String line = "";
			while (isRun) {
				try {
					line = cin.readLine();// 从端口读入一条信息
				} catch (IOException e) {
					this.appendTextArea("输入输出异常\n");
				}
				StringTokenizer st = new StringTokenizer(line, ":");
				String keyword = st.nextToken();// 存储关键字,判断消息类型
				if (keyword.equalsIgnoreCase("QUIT")) {
					try {
						socket.close();
						this.appendTextArea("接收到服务器同意断开信息,套接字关闭\n");
					} catch (IOException e) {
						this.appendTextArea("套接字关闭异常\n");
					}
					isRun = false;
				} else if (keyword.equalsIgnoreCase("PEOPLE")) {
					ArrayList<String> imessage = new ArrayList<String>();
					while (st.hasMoreTokens())
						imessage.add(st.nextToken());
					this.list(imessage);
				} else {
					// 接收的是来自服务器的广播信息
					// 将信息的余下内容全部提取,并去掉首字符(冒号),并显示
					String message = st.nextToken("\0");
					message = message.substring(1);
					this.appendTextArea(message + "\n");
				}
			}
		}
	}
}

二、ServerApp.java


import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Label;

import java.net.*;
import java.io.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList; //引入 ArrayList 类,用于存储客户信息
import java.util.StringTokenizer; //引入 StringTokenizer 类,用于信息分离
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.custom.ScrolledComposite;

import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

public class ServerApp {
	ServerSocket server = null;// server成员变量的作用是用来打开服务器的端口
	ConnectSocket connect = null;
	static ArrayList<Client> clients = new ArrayList<Client>();
//	Socket socket = null;// socket成员变量的作用是用来与客户端建立套接字连接
//	BufferedReader cin = null;// cin成员变量的作用是用来建立输入流
//	PrintStream cout = null;// cout成员变量的作用是用来建立输出流
	Label label;
	Text textPort;//端口输入框
	Button actionListener;//监听按钮
	Text connectionArea, notificationArea;//已连接用户列表、信息显示框
	protected Shell shell;

	/**
	 * Launch the application.
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			ServerApp window = new ServerApp();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window.
	 */
	public void open() {
		Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setSize(680, 515);
		shell.setText("简单聊天系统-服务端");
		//shell.setFont(SWTResourceManager.getFont("宋体", 14, SWT.NORMAL));

		Label label = new Label(shell, SWT.NONE);
		//label.setFont(SWTResourceManager.getFont("宋体", 15, SWT.NORMAL));
		label.setBounds(52, 9, 118, 50);
		label.setText("\u76D1\u542C\u7AEF\u53E3");

		textPort = new Text(shell, SWT.BORDER);
		//textPort.setFont(SWTResourceManager.getFont("宋体", 13, SWT.NORMAL));
		textPort.setBounds(194, 10, 200, 60);
		textPort.setText("4321");

		actionListener = new Button(shell, SWT.NONE);
		//actionListener.setForeground(SWTResourceManager.getColor(SWT.COLOR_LIST_SELECTION));
		//actionListener.setFont(SWTResourceManager.getFont("宋体", 14, SWT.NORMAL));
		actionListener.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				try {
					// 打开服务器端口
					server = new ServerSocket(Integer.parseInt(textPort.getText()));
					notificationArea.append("系统提示:聊天服务器系统开始启动...... \n");
				} catch (IOException e1) { // 捕捉可能产生的异常
					notificationArea.append("服务器端口打开出错\n");
				}
				if (server != null) {
					/* 开始用户连接 */
					ConnectSocket connect = new ConnectSocket();
					connect.start();
				}
			}
		});
		actionListener.setBounds(440, 10, 200, 60);
		actionListener.setText("开始监听");

		connectionArea = new Text(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
		//connectionArea.setFont(SWTResourceManager.getFont("宋体", 11, SWT.NORMAL));
		//connectionArea.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		connectionArea.setBounds(20, 90, 620, 164);
		connectionArea.setEditable(false);

		notificationArea = new Text(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
		//notificationArea.setFont(SWTResourceManager.getFont("宋体", 11, SWT.NORMAL));
		//notificationArea.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		notificationArea.setBounds(20, 270, 620, 179);
		notificationArea.setEditable(false);
	}

	


	public boolean checkName(Client newClient) {
		for (int i = 0; i < clients.size(); i++) {
			// 取出每一个连接对象元素
			Client c = (Client) clients.get(i);
			// 如果不是对象自身但名字相同,则表明出现了重复名称
			if ((c != newClient) && (c.name).equals(newClient.name))
				return false;
		}
		return true;
	}

	public void notifyRoom() {
		// 服务器发送到客户的信息字符串,“PEOPLE”表示是客户列表信息
		String people = "PEOPLE";
		for (int i = 0; i < clients.size(); i++) {
			// 获取每一个服务器—客户交互信息线程
			Client c = (Client) clients.get(i);
			// 将用户名称添加到发送信息字符串
			people += ":" + c.name;
		}
		// 调用信息广播成员方法,将用户列表信息发送到所有客户端
		sendClients(people);
	}

	public void sendClients(String msg) {
		for (int i = 0; i < clients.size(); i++) {
			// 获取每一个服务器—客户交互信息线程
			Client c = (Client) clients.get(i);
			// 通过线程的发送方法将信息发送出去
			c.send(msg);
		}
	}

	public void disconnect(Client c) {
		try {
			Display.getDefault().syncExec(new Runnable() {

				public void run() {

					// 需要操作的ui线程的代码
					connectionArea.append(c.name + "断开连接\n");
				}

			});
			
			// 向客户发送断开信息
			c.send("QUIT");
			clients.remove(c);
			c.socket.close();// 断开连接
		} catch (IOException e) {
			notificationArea.append("客户断开错误\n");
		}
	}
	class Client extends Thread {
		String name; // 用来存储客户的连接姓名
		BufferedReader dis; // 用于实现接受从客户端发送来的数据流
		PrintStream ps; // 用来实现向客户端发送信息的打印流
		Socket socket; // 用于建立套接字
		boolean isRun = true;// 控制 Client 线程运行状态
		// 采用异步方式更新主界面中的图形组件

		public void appendConnectionArea(String str) {
			final String str1 = str;
			Display.getDefault().syncExec(new Runnable() {
				public void run() {
					connectionArea.append(str1);
				}
			});
		}

		
		
		public Client(Socket s) { // Client 线程的构造器
			socket = s; // 将服务器-客户端建立连接所形成的套接字传递到该线程
			try {
				// 存储特定客户 socket 的输入流,接受客户发送到服务器端的信息
				dis = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				// 存储特定客户的输出流,发送服务器信息给客户*/
				ps = new PrintStream(socket.getOutputStream());
				// 读取接收到的信息,该信息为客户登陆信息
				String info = dis.readLine();
				// 将信息用":"分离
				StringTokenizer stinfo = new StringTokenizer(info, ":");
				// 用 head 存储关键区分字
				String head = stinfo.nextToken();
				// 第二个数据段是客户的名称
				name = stinfo.nextToken();
				connectionArea.append("系统消息:" + name + "已经连接\n");
			} catch (IOException e) {
				notificationArea.append("系统消息:用户连接出错\n");
			}
		}

		// 实现向客户端发送信息的方法
		public void send(String msg) {
			ps.println(msg);
			ps.flush();
		}

		// 读取客户端发送过来的信息
		public void run() {
			while (isRun) {
				String line = null;
				try {
					/* 读取客户端发送的信息 */
					line = dis.readLine();
				} catch (IOException e) {
					// 如果出错,则要关闭连接,并更新客户列表信息
					appendConnectionArea("系统消息:读客户信息出错");
					disconnect(this);
					notifyRoom();
					return;
				}
				// 对读入的信息进行分离,以确定信息类型
				StringTokenizer st = new StringTokenizer(line, ":");
				String keyword = st.nextToken();// 关键字,判断消息类型
				if (keyword.equalsIgnoreCase("MSG")) {
					/*
					 * 将接收到的客户聊天信息,通过调用信息广播成员方法, 发送到所有客户端
					 */
					sendClients(line);
					// 如果关键字是 QUIT,则是客户端发送的退出信息
				} else if (keyword.equalsIgnoreCase("QUIT")) {
					// 发送同意断开信息到客户端
					send("QUIT");
					// 关闭连接,并更新客户列表信息
					disconnect(this);
					notifyRoom();
					// 结束当前线程
					isRun = false;
				}
			}
		}
	}
	class ConnectSocket extends Thread {
		public void appendInformation() {
			Display.getDefault().syncExec(new Runnable() {
				public void run() {
					Client c = new Client(socket);
					clients.add(c);
					if (checkName(c)) {
						c.start();
						notifyRoom();
					} else {
						disconnect(c);
					}
				}
			});
		}

		Socket socket;

		public void run() {
			while (true) {
				while (true) {
					try {
						socket = server.accept();
					} catch (IOException e2) {
						connectionArea.append("客户连接失败\n");
					}
					this.appendInformation();
				}
			}
		}
	}

}

三、test.java

public class test {
	public static void main(String[] args) {
		try {
			ClientApp window = new ClientApp();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章