Java-多人聊天小程序

上图啦!!!

结构
首先运行:
Server.java

然后启动:
Client.java

在这里插入图片描述

最后退出客户端:

在这里插入图片描述

代码实现

Client

package chat;

import javax.swing.*;
 
public class Client {
    
    
	
	public static void main(String[] args) {
    
    // 使用Windows的界面风格
		try {
    
    
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		} catch (Exception e) {
    
    
			e.printStackTrace();
		}
		new TCPClient().start();
	}
}

Server

package chat;


import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.swing.*;
 
public class Server implements ActionListener {
    
    
	
	private static final int SERVER_PORT = 2222;
	
	private ServerSocket server;
	private JFrame frame;
	private JPanel panel;
	private JTextArea textArea;
	private JScrollPane scrollPane;
	private JTextField textField;
	private JButton button;
	
	private boolean isStarted = false; // 服务器是否启动
	private List<ChatroomClient> clients = new ArrayList<ChatroomClient>();
	
	public Server() {
    
    
		
		frame = new JFrame("服务器");
		panel = new JPanel();
		
		textArea = new JTextArea();
		textArea.setEditable(false);
		textArea.setLineWrap(true);
		scrollPane = new JScrollPane(textArea);
		scrollPane.setBounds(5, 5, 275, 290);
		scrollPane.setBorder(BorderFactory.createLoweredSoftBevelBorder());
		
		textField = new JTextField();
		textField.setBounds(6, 305, 210, 30);
		button = new JButton("发送");
		button.setBounds(220, 305, 60, 30);
		
		button.addActionListener(this);
		textField.addActionListener(this);
		
		panel.add(scrollPane);
		panel.add(textField);
		panel.add(button);
		panel.setLayout(null);
		
		frame.add(panel);
		frame.setSize(300, 400);
		frame.setLocation((1366 - 640) >> 1, (768 - 400) >> 1);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
	}
	
	public static void main(String[] args) {
    
    
		// 使用Windows的界面风格
		try {
    
    
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		} catch (Exception e) {
    
    
			e.printStackTrace();
		}
		new Server().serverStart();
	}
	
	public void serverStart() {
    
    
		
		while (!isStarted) {
    
     // 无限循环尝试启动服务器
			try {
    
    
				server = new ServerSocket(SERVER_PORT);
				isStarted = true;
				Thread.sleep(500);
			} catch (BindException e) {
    
    
				textArea.setText("端口2222被占用,请关闭对应的程序!\n");
			} catch (IOException e) {
    
    
				e.printStackTrace();
			} catch (InterruptedException e) {
    
    
				e.printStackTrace();
			}
		}
		
		textArea.append("服务器启动,等待客户端连接……\n");
		try {
    
    
			// 无限循环检测是否有客户端加入,有则加到list
			while (isStarted) {
    
    
				Socket s = server.accept();
				ChatroomClient client = new ChatroomClient(s);
				clients.add(client);
				client.start();
			}
		} catch (IOException e) {
    
    
			e.printStackTrace();
		} finally {
    
    
			try {
    
    
				server.close();
			} catch (IOException e) {
    
    
				e.printStackTrace();
			}
		}
		
	}
	
	// 服务器发送消息
	public void send() {
    
    
		
		if (textField.getText().length() < 1) {
    
     // 没有输入东西
			return;
		} else if (clients.size() == 0) {
    
    
			textArea.append("无客户端连接!\n");
			return;
		}
		
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String s = "服务器    " + dateFormat.format(new Date()) + "\n    " + textField.getText() + "\n";
		textArea.append(s);
		
		// 循环给列表中的客户端发送信息
		for (int i = 0; i < clients.size(); ++i) {
    
    
			ChatroomClient client = clients.get(i);
			client.send(s);
		}
		textField.setText(null);
	}
	
	public void actionPerformed(ActionEvent arg0) {
    
    
		send();
	}
	
	// Inner Class ChatroomClient
	class ChatroomClient extends Thread {
    
    
		
		private Socket client;
		private DataInputStream in;
		private DataOutputStream out;
		
		//private boolean isConnected = false;
		
		// 客户端初始化
		public ChatroomClient(Socket client) {
    
    
			this.client = client;
			try {
    
    
				in = new DataInputStream(client.getInputStream());
				out = new DataOutputStream(client.getOutputStream());
			} catch (IOException e) {
    
    
				e.printStackTrace();
			}
 
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			textArea.append("客户端已连接  " + dateFormat.format(new Date()) + "\n");
			textArea.append("地址:" + client.getInetAddress().getHostAddress() + "\n端口:" + client.getPort() + "\n\n");
		}
		
		// 发送消息
		public void send(String str) {
    
    
			
			try {
    
    
				out.writeUTF(str);
				out.flush();
			} catch (IOException e) {
    
    
				clients.remove(this);
				textArea.append("客户端已退出,从列表删除!\n");
			}
		}
		
		public void run() {
    
    
			
			try {
    
    
				while (true) {
    
    
					textArea.setCaretPosition(textArea.getDocument().getLength()); // 显示JTextArea最末
					
					String str = in.readUTF();
					//str = str.substring(0, 3) + (clients.indexOf(this) + 1) + str.substring(3);
					textArea.append(str);
					
					for (int i = 0; i < clients.size(); ++i) {
    
    
						ChatroomClient client = clients.get(i);
						client.send(str);
					}
					
					Thread.sleep(100); // 每100ms读取对方信息一次
				}
			} catch (IOException e) {
    
    
				textArea.append("客户端断开连接!\n");
				clients.remove(this);
			} catch (InterruptedException e) {
    
    
				e.printStackTrace();
			} finally {
    
    
				clients.remove(this);
				try {
    
    
					if (in != null)
						client.close();
					if (out != null)
						client.close();
					if (client != null)
						client.close();
				} catch (IOException e) {
    
    
					e.printStackTrace();	}	}	}	}	}

TCPClient

package chat;

import java.awt.Color;
import java.awt.event.*;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;


class TCPClient extends Thread implements ActionListener, MouseListener {
    
    
	
	private String des = "127.0.0.1"; // 服务器地址
	private int port = 2222; // 服务器端口
	
	private Socket client;
	private DataInputStream in;
	private DataOutputStream out;
	
	private JFrame frame;
	private JPanel panel;
	private JTextArea textArea;
	private JScrollPane scrollPane;
	private JTextField textField;
	private JTextField tfDes, tfPort;
	private JLabel label1, label2, addrChange;
	private JButton button;
	
	private boolean isConnected = false; // 是否连接上
	
	public TCPClient() {
    
    
		
		frame = new JFrame("客户端");
		panel = new JPanel();
		
		textArea = new JTextArea();
		textArea.setEditable(false);
		textArea.setLineWrap(true);
		scrollPane = new JScrollPane(textArea);
		scrollPane.setBounds(5, 5, 275, 290);
		scrollPane.setBorder(BorderFactory.createLoweredSoftBevelBorder());
		
		textField = new JTextField();
		textField.setBounds(6, 305, 210, 30);
		textField.addActionListener(this);
		button = new JButton("发送");
		button.setBounds(220, 305, 60, 30);
		button.addActionListener(this);
		
		label1 = new JLabel("服务器地址:");
		label1.setBounds(10, 340, 75, 20);
		tfDes = new JTextField(des);
		tfDes.setBounds(75, 341, 80, 20);
		tfDes.setBorder(null);
		
		label2 = new JLabel("端口:");
		label2.setBounds(160, 340, 40, 20);
		tfPort = new JTextField(Integer.toString(port));
		tfPort.setBounds(190, 341, 35, 20);
		tfPort.setBorder(null);
		
		addrChange = new JLabel("连接");
		addrChange.setForeground(Color.BLUE);
		addrChange.setBounds(235, 337, 30, 20);
		addrChange.setBorder(BorderFactory.createRaisedBevelBorder());
		addrChange.addMouseListener(this);
		
		panel.add(scrollPane);
		panel.add(textField);
		panel.add(button);
		panel.add(label1);
		panel.add(tfDes);
		panel.add(label2);
		panel.add(tfPort);
		panel.add(addrChange);
		panel.setLayout(null);
		
		frame.add(panel);
		frame.setSize(300, 400);
		frame.setLocation(1366 >> 1, (768 - 400) >> 1);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	// 发送消息
	public void send() {
    
    
		
		if (textField.getText().length() < 1) {
    
     // 没有输入东西
			return;
		} else if (out == null || client.isClosed()) {
    
    
			textArea.append("没有与服务器连接!\n");
			return;
		}
		try {
    
    
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			out.writeUTF(InetAddress.getLocalHost().getHostName() + "    " + dateFormat.format(new Date()) + "\n    " + textField.getText() + "\n");
			out.flush();
			//textArea.append("客户端    " + new Date().toLocaleString() + "\n    " + textField.getText() + "\n");
			textField.setText(null);
		} catch (IOException e) {
    
    
			e.printStackTrace();
		}
		
	}
	
	public void actionPerformed(ActionEvent arg0) {
    
    
		send();}
	
	public void mouseClicked(MouseEvent arg0) {
    
    }
	
	public void mouseEntered(MouseEvent arg0) {
    
    }
	
	public void mouseExited(MouseEvent arg0) {
    
    }

	public void mousePressed(MouseEvent arg0) {
    
    
		addrChange.setBorder(BorderFactory.createLoweredBevelBorder());
	}

	public void mouseReleased(MouseEvent arg0) {
    
    
		addrChange.setBorder(BorderFactory.createRaisedBevelBorder());
		if (!tfDes.getText().matches(
				"([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}")
				|| !tfPort.getText().matches(
				"[0-9]|[1-9]\\d|[1-9]\\d{2}|[1-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5]")) {
    
    
			textArea.append("请输入正确的地址和端口!!\n");
			return;
		}
		String tmpd = tfDes.getText();
		int tmpp = Integer.parseInt(tfPort.getText());
		if (des.equals(tmpd) && port == tmpp) {
    
    
			if (isConnected == true)
				textArea.append("已经和指定服务器连上,请不要重复连接!\n");
			return;
		}
		des = tmpd;
		port = tmpp;
		try {
    
    
			if (in != null)
				in.close();
			if (out != null)
				out.close();
			if (client != null)
				client.close();
		} catch (IOException e) {
    
    
			e.printStackTrace();
		}
		if (isConnected == false) {
    
    
			textArea.append("正在连接服务器……\n");
			textArea.append("目标地址:" + des + "\n");
			textArea.append("目标端口:" + port + "\n");
		} else {
    
    
			textArea.append("用户中断当前连接!\n");
		}
		isConnected = false;
	}
	
	public void run() {
    
    
		
		while (true) {
    
    
			
			textArea.append("正在连接服务器……\n");
			textArea.append("目标地址:" + des + "\n");
			textArea.append("目标端口:" + port + "\n");
			while (!isConnected) {
    
    
				try {
    
    
					client = new Socket(des, port);
					in = new DataInputStream(client.getInputStream());
					out = new DataOutputStream(client.getOutputStream());
					isConnected = true;
					Thread.sleep(500);
				} catch (IOException e) {
    
    
					continue;
				} catch (InterruptedException e) {
    
    
					e.printStackTrace();
				}
			}
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			textArea.append("连接服务器成功!" + dateFormat.format(new Date()) + "\n\n");
			
			try {
    
    
				while (isConnected) {
    
    
					textArea.setCaretPosition(textArea.getDocument().getLength()); // 显示JTextArea最末
					textArea.append(in.readUTF()); // 每100ms读取对方信息一次
					Thread.sleep(100);
				}
			} catch (IOException e) {
    
    
				textArea.append("与服务器失去连接!\n\n");
			} catch (InterruptedException e) {
    
    
				e.printStackTrace();
			} finally {
    
    
				try {
    
    
					if (in != null)
						in.close();
					if (out != null)
						out.close();
					if (client != null)
						client.close();
				} catch (IOException e) {
    
    
					e.printStackTrace();
				}
				isConnected = false;
			}}}}

猜你喜欢

转载自blog.csdn.net/GodOuO/article/details/104727698