JAVA实验三-多人聊天室可视化

编写一个 Java 应用程序,实现图形界面多人聊天室(多线程实现),要求聊天室窗口标题是 “欢迎使用 XXX 聊天室应用”,其中 XXX 是自己的班级姓名学号,如“软件 171 张三 1234”。

客户端

import java.awt.BorderLayout;

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import java.io.*;
class Login extends JFrame implements ActionListener{
	//用户名
	JPanel jp1=new JPanel();
	JLabel jl1=new JLabel("用户名");
	public JTextField jtf1=new JTextField(15);
	//密码
	JPanel jp2=new JPanel();
	JLabel jl2=new JLabel("密码");
	JPasswordField jpf2 = new JPasswordField(15);
	//登入取消按钮
	JPanel jp3=new JPanel();
	JButton jbt1=new JButton("登入");
	JButton jbt2=new JButton("取消");
	
	public Login() {
		// TODO 自动生成的构造函数存根
		this.setTitle("客服端登入窗口");
		Container con =this.getContentPane();
		con.setLayout(new FlowLayout());
		//用户名
		jp1.add(jl1);
		jp1.add(jtf1);
		jtf1.addActionListener(this);
		//密码
		jpf2.setEchoChar('*');  //用*显示密码框输入的数据
		jp2.add(jl2);
		jp2.add(jpf2);
		jpf2.addActionListener(this);
		//登入取消按钮
		jp3.add(jbt1);
		jp3.add(jbt2);
		//添加到当前窗口容器
		con.add(jp1);
		con.add(jp2);
		con.add(jp3);
		this.setSize(500, 300);    //设置窗体大小
		setLocationRelativeTo(null); //设置窗口居中
		this.setResizable(false);  //窗体大小设置为不可改
		this.setVisible(true);  //窗体设置为可见
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		//光标聚焦在用户框中
		jtf1.requestFocus(); 
		//为登入按钮添加监听器
		jbt1.addActionListener(new ActionListener() { 
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO 自动生成的方法存根
				String name=jtf1.getText();
				String password=new String(jpf2.getPassword()); //获取密码框中的密码
				try {
					if(password.equals("123")) {
						setVisible(false);
						new Client(jtf1.getText());
					}
					else {
						JOptionPane.showConfirmDialog(null, "用户名或密码错误!",
								"提示",JOptionPane.DEFAULT_OPTION);
					}
				} catch (Exception e2) {
					// TODO: handle exception
					e2.printStackTrace();
				}
			}
		});
		jbt2.addActionListener(new ActionListener() { //为取消按钮添加监听器
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO 自动生成的方法存根
				try {
					setVisible(false);
				} catch (Exception e2) {
					// TODO: handle exception
				}
			}
		});
	}
	//移动光标聚集
	public void actionPerformed(ActionEvent e) {
		Object o=e.getSource();
		if(o==jtf1) {
			jpf2.requestFocus();
		}
	}
}

public class Client extends JFrame  {
	public DataOutputStream dos=null;
	public DataInputStream dis=null;
	public Socket s=null;
	public ServerSocket sc=null;
	//
	public JTextArea jta=new JTextArea(10,20);
	public JTextField jtf=new JTextField(20);
	public JScrollPane jsp = new JScrollPane(jta);
	static final String CONNSTR="127.0.0.1";
	public String ClientName="";

	//构造函数初始化
	Client(String tClientName) throws IOException{
		ClientName=tClientName;
		this.setTitle("客服端:"+ClientName);
		jta.setEditable(false); //文本显示框不可编辑
		this.add(jtf,BorderLayout.SOUTH);
		this.add(jsp,BorderLayout.CENTER);
		//默认的设置是超过文本框才会显示滚动条,以下设置让滚动条一直显示
		jsp.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		//连接服务器
		
		try {
			s=new Socket(CONNSTR,9995);
			new ThreadClient(s,this).start();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			JOptionPane.showConfirmDialog(null, "用户连接服务器失败",
					"提示",JOptionPane.DEFAULT_OPTION);
		}
		//发送登入信息到服务器
		String firstStr="\""+ClientName+"\":"+"登入成功";
		DataOutputStream firstdataOutputStream = new DataOutputStream(s.getOutputStream());
		//发送用户名到服务端
		firstdataOutputStream.writeUTF(firstStr);
		firstdataOutputStream.flush();
		//
		this.setBounds(300,300,300,400);		
		//this.setSize(500, 300);    //设置窗体大小
		setLocationRelativeTo(null); //设置窗口居中
		this.setVisible(true);  //窗体设置为可见
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		jtf.requestFocus();
		//
		
		jtf.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO 自动生成的方法存根
				String str=jtf.getText();
				try {
					if(str.length()>0) {
						str="\""+ClientName+"\":"+str;
						sendMessage(str, s);
						jtf.setText("");
					}
				} catch (Exception e2) {
					// TODO: handle exception
					e2.printStackTrace();
					str="\""+ClientName+"\":"+"已退出";
					sendMessage(str,s);
				}
				
			}
		});
	}
	//客服端发送信息到服务器
	protected void sendMessage(String message, Socket s) {
		try {
			DataOutputStream dos = new DataOutputStream(s.getOutputStream());
			dos.writeUTF(message);
			dos.flush();	
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		new Login();
	}
}
//定义线程类,读取服务器发送的信息
class ThreadClient extends Thread {
	private Socket s;
	private Client clientChat;

	ThreadClient(Socket socket, Client clientChat) {
		this.s = socket;
		this.clientChat = clientChat;
	}
	@Override
	public void run() {
		String message;
		try {
			while (true) {
					DataInputStream DataInputStream = new DataInputStream(s.getInputStream());
					message = DataInputStream.readUTF();
					clientChat.jtf.setText("");
					clientChat.jta.append(message+"\n");
				}
		}
		catch (IOException e) {
			// TODO Auto-generated catch block
				e.printStackTrace();
				message="\""+clientChat.ClientName+"\":"+"已退出";
				clientChat.sendMessage(message,s);
		}
	}
}

服务端

import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

import javax.naming.ldap.LdapName;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Server extends JFrame {
	//static List<Socket>ls=new ArrayList<Socket>();
	//static List<String>lname=new ArrayList<String>();
	public static Map<Socket,String> socketsMaps 
	= Collections.synchronizedMap(new HashMap<Socket,String>());
	//
	ServerSocket sc=null;
	Socket s=null;
	public JTextArea jta=new JTextArea(10,20);
	public JScrollPane jsp=new JScrollPane(jta);
	public String ServerName="服务器";
	static int number=1;
	Server() throws IOException{
		super();
		setTitle("服务器");
		jta.setEditable(false); //文本显示框不可编辑
		this.add(jsp,BorderLayout.CENTER);
		  //默认的设置是超过文本框才会显示滚动条,以下设置让滚动条一直显示
		jsp.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		//this.add(jta,BorderLayout.CENTER);  //不需要重复添加
		this.setBounds(300,300,300,400);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//
	}
	public void init() {
		int count = 0; // 记录登录到该服务器的客户端个数
			try {
				sc = new ServerSocket(9995); // 创建一个ServerSocket对象,端口号为1906
				jta.append("服务器已启动"+'\n');
				while (true) {
					Socket socket=sc.accept();
					new ThreadServer(socket,this).start();
				}
			}
			catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
			
	}
	
	public static void main(String[] args) throws IOException{
		new Server().init();
	}
}

class ThreadServer extends Thread {
	private Socket ts;
	private Server tsr;
	ThreadServer(){};
	ThreadServer(Socket s,Server sr)
	{
		this.ts = s;
		this.tsr=sr;
	}
	public void run() {
		
		try {
			while(true)
			{
				DataInputStream dis = new DataInputStream(ts.getInputStream());
				String message=dis.readUTF();
				if(message.endsWith(":登入成功")) {
					message.replaceAll(":登入成功", "");
					tsr.socketsMaps.put(ts,message);
				}
				tsr.jta.append(message+'\n');
				Set<Socket> sockets = tsr.socketsMaps.keySet();
				for(Socket tts : sockets) {
					DataOutputStream dos = new DataOutputStream(tts.getOutputStream());
					dos.writeUTF(message);
					dos.flush();
				}
			}
		}
		catch (IOException e2) {
			// TODO: handle exception
			e2.printStackTrace();
		}
	}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 8
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值