通过Swing编程结合Socket模拟多人聊天程序

用户登录

ClientLogin.java

package QQDome;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;


@SuppressWarnings("serial")
public class ClientLogin extends JFrame {
	private JTextField nameTxt;
	private JPasswordField jPasswordField;
	
	public ClientLogin() {
		// TODO 自动生成的构造函数存根
		this.init();
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setVisible(true);
	}
	
	public void init(){
		this.setTitle("聊天登录界面");
		//this.setSize(330, 230);
		this.setBounds(200, 500, 340, 230);
		int x = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth();
		int y = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
		this.setLocation(x-this.getWidth() / 2, y-this.getHeight() / 2);
		this.setResizable(false);
		this.setVisible(true);
		//登录信息面板
		JPanel mainPanel = new JPanel();
		Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
		mainPanel.setBorder(BorderFactory.createTitledBorder(border, "输入登录信息", TitledBorder.CENTER, TitledBorder.TOP));
		this.add(mainPanel,BorderLayout.CENTER);
		mainPanel.setLayout(null);
		JLabel nameLbl = new JLabel("请输入昵称: ");
		nameLbl.setBounds(30,30,80,22);
		mainPanel.add(nameLbl);
		nameTxt = new JTextField();
		nameTxt.setBounds(115,30,120,22);
		mainPanel.add(nameTxt);
		JLabel pwdLbl = new JLabel("请输入密码: ");
		pwdLbl.setBounds(30,60,80,22);
		mainPanel.add(pwdLbl);
		jPasswordField = new JPasswordField();
		jPasswordField.setBounds(115, 60, 120, 22);
		mainPanel.add(jPasswordField);
		//按钮面板放置在JFrame的南边
		JPanel btnPanel = new JPanel();
		btnPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
		this.add(btnPanel, BorderLayout.SOUTH);
		JButton resetBtn = new JButton("重置");
		resetBtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO 自动生成的方法存根
				nameTxt.setText("");
				jPasswordField.setText("");
			}
		});
		btnPanel.add(resetBtn);
		JButton submitBtn = new JButton("登录");
		submitBtn.addActionListener(new LoginAction(this));
		btnPanel.add(submitBtn);
	}
	
	//登录时间处理类
	class LoginAction implements ActionListener{
		private JFrame self;
		public LoginAction(JFrame self) {
			
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO 自动生成的方法存根
			System.out.println("用户名是" + nameTxt.getText() + ",密码是" + new String(jPasswordField.getPassword()));
			try {
				//链接服务器
				Socket socket = new Socket("127.0.0.1", 8888);
				
				//连接上之后,显示聊天窗口
				new ChatClient(socket, nameTxt.getText());
				
				//本窗口销毁
				self.dispose();
			}catch (UnknownHostException e1) {
				// TODO: handle exception
				e1.printStackTrace();
				JOptionPane.showConfirmDialog(self, "找不到指定的服务器!","链接失败", JOptionPane.OK_OPTION,JOptionPane.ERROR_MESSAGE);
			}catch (IOException e1) {
				// TODO: handle exception
				e1.printStackTrace();
				JOptionPane.showConfirmDialog(self, "找不到指定的服务器!","链接失败", JOptionPane.OK_OPTION,JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
	
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		JFrame.setDefaultLookAndFeelDecorated(true);
		JDialog.setDefaultLookAndFeelDecorated(true);
		new ClientLogin();
	}

}

聊天室的客户端

ChatClient.java

package QQDome;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;

@SuppressWarnings("serial")
public class ChatClient extends JFrame{
	//负责跟服务器通讯的Socket
	private Socket socket;
	//要发送的内容区域
	private JTextArea sendArea;
	//聊天记录区域
	private JTextArea contentArea;
	//当前用户的昵称
	private String name;
	
	
	public ChatClient(Socket socket,String name) {
		// TODO 自动生成的构造函数存根
		this.name = name;
		this.socket = socket;
		this.init();
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setVisible(true);
		
		//启动一个单独的线程关门从服务器中读取数据
		ClientThread thread = new ClientThread(socket, contentArea);
		thread.start();
	}
	
	public void init() {
		this.setTitle("我的聊天室");
		this.setSize(300,400);
		int x = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth();
		int y = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
		this.setLocation(x-this.getWidth()/2, y-this.getHeight()/2);
		this.setVisible(false);
		
		contentArea = new JTextArea();
		contentArea.setLineWrap(true);
		JScrollPane logPane = new JScrollPane(contentArea,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		
		sendArea = new JTextArea();
		sendArea.setLineWrap(true);
		JScrollPane sendPane = new JScrollPane(sendArea,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		
		//创建一个分割窗口
		JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,logPane,sendPane);
		splitPane.setDividerSize(10);
		this.add(splitPane,BorderLayout.CENTER);
		
		//按钮面板
		JPanel btnPanel = new JPanel();
		btnPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
		this.add(btnPanel, BorderLayout.SOUTH);
		
		JLabel nameLbl = new JLabel("昵称: " + this.name + "  ");
		btnPanel.add(nameLbl);
		
		JButton resetBtn = new JButton("关闭");
		resetBtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO 自动生成的方法存根
				
			}
		});
		
		btnPanel.add(resetBtn);
		JButton submitBtn = new JButton("发送");
		//发送数据到服务器
		submitBtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO 自动生成的方法存根
				//要发送的内容
				String str = sendArea.getText();
				SimpleDateFormat formater = new SimpleDateFormat("HH:mm:ss"); //设定时间格式
				String time = formater.format(new Date());
				String sendStr = name + "  " + time + "说: " + str;
				//往服务器发送
				PrintWriter out = null;
				try {
					out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
					out.println(sendStr);
					out.flush();
				}catch (IOException e1) {
					// TODO: handle exception
					e1.printStackTrace();
				}
				sendArea.setText("");
			}
		});
		btnPanel.add(submitBtn);
	}
	
	//客户端跟服务器通讯的线程类
	class ClientThread extends Thread{
		//客户端跟服务器连接上的Socket
		private Socket socket;
		//聊天记录区域
		private JTextArea contentArea;
		
		public ClientThread(Socket socket,JTextArea contentArea) {
			this.socket = socket;
			this.contentArea = contentArea;
		}
		public void run() {
			BufferedReader bufferedReader = null;
			try {
				bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				//从输入流中读取数据添加到聊天记录区域中
				String str = null;
				while((str = bufferedReader.readLine()) != null) {
					contentArea.append(str);
					contentArea.append("\n");
				}
			}catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();
			}finally {
				if (bufferedReader!=null) {
					try {
						bufferedReader.close();
					}catch (IOException e) {
						// TODO: handle exception
						e.printStackTrace();
					}
				}
			}
		}
	}

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Socket socket = null;
		String name = null;
		new ChatClient(socket,name);
	}

}

聊天室的服务器端

ChatServer.java

package QQServer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class ChatServer {
	
	//用来保存所有客户端的socket信息
	private ArrayList<Socket> sockets = new ArrayList<Socket>();
	public ChatServer() throws IOException{
		this.init();
	}
	
	public void init() throws IOException {
		ServerSocket ss =new ServerSocket(8888);
		System.out.println("服务器已经开始监听8888端口了...");
		//监听并接受客户端
		while(true) {
			Socket socket = ss.accept();
			sockets.add(socket);
			String ip = socket.getInetAddress().getHostAddress();
			System.out.println("有一个客户端来了他的IP地址是: " + ip);
			//针对每一个客户端都启动一个线程单独跟他通信
			Thread thread = new Thread(new ServerRunner(sockets,socket));
			thread.start();
		}
	}
	
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		try {
			new ChatServer();
		}catch (IOException e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
	//服务器跟客户端通信的线程类
	//把某个客户端发过来的数据转发给所有客户端
	class ServerRunner implements Runnable{
		private ArrayList<Socket> sockets;
		private Socket currentsocket;
		public ServerRunner(ArrayList<Socket> sockets,Socket currentsocket) {
			// TODO 自动生成的构造函数存根
			this.sockets = sockets;
			this.currentsocket = currentsocket;
		}
		@Override
		public void run() {
			// TODO 自动生成的方法存根
			String ip = currentsocket.getInetAddress().getHostAddress();
			BufferedReader bReader = null;
			try {
				bReader = new BufferedReader(new InputStreamReader(currentsocket.getInputStream()));
				String str = null;
				while((str = bReader.readLine()) != null){
					System.out.println(ip + "说:" + str);
					//往所有客户端socket写信息
					for(Socket temp:sockets) {
						PrintWriter pw = new PrintWriter(new OutputStreamWriter(temp.getOutputStream()));
						pw.println(str);
						pw.flush();
					}
				}
			} catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
		
	}

}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java Socket编程可以用于实现多人聊天室。以下是一个简单的Java多人聊天室的代码示例: Server端代码: ```java import java.io.*; import java.net.*; import java.util.*; public class Server { ArrayList<PrintWriter> clientOutputStreams; public class ClientHandler implements Runnable { BufferedReader reader; Socket socket; public ClientHandler(Socket clientSocket) { try { socket = clientSocket; InputStreamReader isReader = new InputStreamReader(socket.getInputStream()); reader = new BufferedReader(isReader); } catch (Exception ex) { ex.printStackTrace(); } } public void run() { String message; try { while ((message = reader.readLine()) != null) { System.out.println("read " + message); tellEveryone(message); } } catch (Exception ex) { ex.printStackTrace(); } } } public static void main (String[] args) { new Server().go(); } public void go() { clientOutputStreams = new ArrayList<PrintWriter>(); try { ServerSocket serverSock = new ServerSocket(5000); while(true) { Socket clientSocket = serverSock.accept(); PrintWriter writer = new PrintWriter(clientSocket.getOutputStream()); clientOutputStreams.add(writer); Thread t = new Thread(new ClientHandler(clientSocket)); t.start(); System.out.println("got a connection"); } } catch (Exception ex) { ex.printStackTrace(); } } public void tellEveryone(String message) { Iterator<PrintWriter> it = clientOutputStreams.iterator(); while (it.hasNext()) { try { PrintWriter writer = (PrintWriter) it.next(); writer.println(message); writer.flush(); } catch (Exception ex) { ex.printStackTrace(); } } } } ``` Client端代码: ```java import java.io.*; import java.net.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Client { JTextArea incoming; JTextField outgoing; BufferedReader reader; PrintWriter writer; Socket sock; public static void main(String[] args) { new Client().go(); } public void go() { JFrame frame = new JFrame("Ludicrously Simple Chat Client"); JPanel mainPanel = new JPanel(); incoming = new JTextArea(15,50); incoming.setLineWrap(true); incoming.setWrapStyleWord(true); incoming.setEditable(false); JScrollPane qScroller = new JScrollPane(incoming); qScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); qScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); outgoing = new JTextField(20); JButton sendButton = new JButton("Send"); sendButton.addActionListener(new SendButtonListener()); mainPanel.add(qScroller); mainPanel.add(outgoing); mainPanel.add(sendButton); setUpNetworking(); Thread readerThread = new Thread(new IncomingReader()); readerThread.start(); frame.getContentPane().add(BorderLayout.CENTER, mainPanel); frame.setSize(400,500); frame.setVisible(true); } private void setUpNetworking() { try { sock = new Socket("127.0.0.1", 5000); InputStreamReader streamReader = new InputStreamReader(sock.getInputStream()); reader = new BufferedReader(streamReader); writer = new PrintWriter(sock.getOutputStream()); System.out.println("networking established"); } catch (IOException ex) { ex.printStackTrace(); } } public class SendButtonListener implements ActionListener { public void actionPerformed(ActionEvent ev) { try { writer.println(outgoing.getText()); writer.flush(); } catch (Exception ex) { ex.printStackTrace(); } outgoing.setText(""); outgoing.requestFocus(); } } public class IncomingReader implements Runnable { public void run() { String message; try { while ((message = reader.readLine()) != null) { System.out.println("client read " + message); incoming.append(message + "\n"); } } catch (Exception ex) { ex.printStackTrace(); } } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值