2020暑假集训项目——Java简易聊天室

2022-08-01,,,,

经过一周的学习与搬砖,我成功的完成了暑假集训的第一个项目——Java简易聊天室,这里对整个项目做一个总结。(文末附下载地址
本项目支持的功能:
1.可同时开启多个客户端进行多人聊天;
2.可与在线的所有用户进行群聊;
3.可选择一个在线的用户进行私聊。
4.实时更新的用户列表(用户登陆或者退出时均会在其他已经登陆的用户界面上显示);
5.可将文件上传至服务端;
6.可将已经上传过的文件下载至本地。
PS:
1.本项目仅为学习用项目;
2.本项目的服务器在自己的电脑上运行,客户端也在自己电脑上开启。所有聊天消息,文件传输都基于网络传输进行。

项目准备

在D盘准备upload文件夹和updown文件夹

项目效果

用于开启客户端的界面:

客户端UI界面

群聊

选择私聊用户及选择后的效果

私聊

上传文件

下载文件

项目编写时间安排
第一天:看视频、看书,复习IO流知识,学习多线程知识;
第二天 :看视频学习网络编程知识,开始构思项目流程,在网上找别人的作品并学习思路;
第三天:完成UI界面的设计 对群聊私聊的实现有了初步的规划;
第四天:完成群聊私聊的功能,解决了一些逻辑性问题;
第五天:开始编写文件上传 并对出现的bug进行解决,将界面与功能联系在一起;
第六天:解决文件上传的bug,完成下载功能的实现。
项目难点及思路
1.项目初期,通过看书以及优秀学长的代码,了解到使用一个编写一个Map类用于储存用户名与输出流的对应关系(或者与Socket客户端),这里使我少走了很多弯路,也使我的群聊与私聊功能实现的比较容易;
2.在完成文件上传时,刚开始的思路是使用TCP传输,但我的整个项目都是基于带有标识符的客户端与服务器的收发流来完成的,如果采用TCP 则文件的前后将带上标识符,这破坏了文件的完整性。因此在思考后 :我给出了三种解决方案,并一一尝试:
(1)在接收到带有文件上传标识符的流后,服务器开启另外的线程来接收文件;但这个方法在我仔细思考后pass掉了,因为它与下面的第二种方案效果差不多,而且更复杂低效;
(2)在上传文件时直接进行上传,不带任何标识符,而在用于接收流的服务端线程类ServerThread里,是用if else if else 来接收消息的,我只需要把接收文件的代码写在else 里就可以了,这样虽然文件没有带标识符,还是可以被下载到。
但这个方法在尝试后还是被pass了,因为接收到的文件为空,发生了失真。(项目写完后进行反思时还是觉得是自己的代码有问题);
(3)在群聊私聊时使用了TCP协议,但是在文件上传与下载时不一定使用TCP协议,可以使用UDP协议。因此我使用UDP进行文件传输的功能,并且获得了成功。

项目的基本思路就是这样,接下来是项目最重要的五个类。

package Client;

import UI.ClientUI;
import tool.CrazyitProtocol;

import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.ArrayList;

/*
客户端主类
 */
public class Client {
    private static final int SERVER_PORT = 1211;//端口号
    private Socket socket;
    private PrintStream ps;
    private BufferedReader brServer;
    private BufferedReader In;
    public String name = "魑魅魍魉魑魅魍魉魑魅魍魉";
    public ClientUI ui;
    //客户端构造器
    public Client(ClientUI clientUI) throws IOException//传入ui界面 对JTextArea和JTextFiled进行管理
    {
        this.ui = clientUI;
        init(ui);
    }
    public void init(ClientUI ui) throws IOException {
        //获取用户输入的名字
        String name = ui.getNameJT();
        //验空
        if(name.equals(""))
        {
            ui.new_Msg("用户名不能为空!");
            return;
        }
        socket = new Socket("127.0.0.1",SERVER_PORT);
        ps = new PrintStream(socket.getOutputStream());
        brServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        try {
                //发送一个带有登录标识符的流
                ps.println(CrazyitProtocol.USER_ROUND + name + CrazyitProtocol.USER_ROUND);
                //接收服务器传回的值
                String result = brServer.readLine();
                //用户名重复
                if(result.equals(CrazyitProtocol.NAME_REP))
                {
                    ui.setTalk("用户名重复!请重新输入");
                    socket.close();
                }
                //登录成功
                if(result.equals(CrazyitProtocol.LOGIN_SUCCESS))
                {
                    ui.setTalk("登录成功!");
                    ui.setNameJTEdit();
                    //开启一个客户端接收服务器消息的线程
                    new ClientThread(brServer,ui).start();
                    //进行用户列表的更新及文件列表的获取
                    ps.println(CrazyitProtocol.UPDATE1+ "" + CrazyitProtocol.UPDATE1);
                    ps.println(CrazyitProtocol.DOWN_SIGN + "" +CrazyitProtocol.DOWN_SIGN);
                }
        }
        catch (UnknownHostException e)
        {
            ui.setTalk("找不到远程服务器,请确定服务器已经启动!");
            closeRs();
        }
        catch (IOException e)
        {
            ui.setTalk("网络异常!请检查网络状况");
            closeRs();
        }
    }
    //发送消息
    public void readAndSend() {
        try {
            String line = ui.getMsg();
            //验空
            if (line.equals("")) {
                ui.new_Msg("发送的消息不能为空!");
                return;
            }
            //私聊
            //如果UI界面的文本输入框内的文字 起始为@而且“:”的位置大于0(即输入了要私聊的名字) 发送带有私聊标识符的消息给服务器
            if (line.indexOf(":") > 0 && line.startsWith("@")) {
                String name = ui.getNameJT();
                //不能私聊自己的判断
                if((line.indexOf(name)>0)&&(line.indexOf(name) < line.indexOf(":")))
                {
                    ui.new_Msg("不能给自己发消息!");
                    ui.setMsg("");
                    return;
                }
                //将@分割掉
                line = line.substring(1);
                ps.println(CrazyitProtocol.PRIVATE_ROUND + line.split(":")[0] + CrazyitProtocol.SPLIT_SIGH +
                        line.split(":")[1] + CrazyitProtocol.PRIVATE_ROUND);
                //设置UI界面消息框为空
                ui.setMsg("");
            }
            //群聊
            //发送带有群聊标志的消息
            else {
                ps.println(CrazyitProtocol.MSG_ROUND + line + CrazyitProtocol.MSG_ROUND);
                ui.setMsg("");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //使用Udp进行文件上传
    public void UpDate() throws IOException {
        //获取要上传文件的文件名
        String filename = JOptionPane.showInputDialog("请输入文件名:");
        //验空
        if (filename.equals("") == false) {
            //发送带有文件上传的流
            ps.println(CrazyitProtocol.FILE_ROUND + filename + CrazyitProtocol.FILE_ROUND);
            DatagramSocket datagramSocket = null;
            try {
                datagramSocket = new DatagramSocket(1210);
            } catch (SocketException socketException) {
                socketException.printStackTrace();
            }
            //创建文件输入流,读取本地文件
            FileInputStream fileInputStream = null;
            try {
                fileInputStream = new FileInputStream(new File("src\\txt\\" + filename));
            } catch (FileNotFoundException fileNotFoundException) {
                fileNotFoundException.printStackTrace();
            }
            //读取输入流中的数据
            byte[] bytes = new byte[0];//创建数组
            try {
                bytes = new byte[fileInputStream.available()];
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
            try {
                fileInputStream.read(bytes);//给数组写入数据
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
            //创建数据载体DatagramPacket
            DatagramPacket datagramPacket = null;
            try {
                datagramPacket = new DatagramPacket(bytes, 0, bytes.length, InetAddress.getByName("127.0.0.1"), 1211);
            } catch (UnknownHostException unknownHostException) {
                unknownHostException.printStackTrace();
            }
            //发送
            try {
                datagramSocket.send(datagramPacket);
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
            //发送完成后向服务器发送一条带有文件列表更新标识符的消息 使服务器更新每个用户的文件列表
            ps.println(CrazyitProtocol.DOWN_SIGN + "" + CrazyitProtocol.DOWN_SIGN);
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
            //成功上传,弹框
            datagramSocket.close();
            JOptionPane.showMessageDialog(null, "上传成功");
        }
    }
    //关闭流的方法
        private void closeRs(){
        try {
            if(brServer != null)
            {
                brServer.close();
            }
            if( ps!= null)
            {
                ps.close();
            }
            if( socket!= null)
            {
                socket.close();
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    //获取用户输入的名字
    public String get_name()
    {
        return name;
    }
    public void colse1() throws IOException {
        socket.close();
    }
    //关闭界面时 调用此方法关闭socket
    public void close() throws IOException {
        ps.println(CrazyitProtocol.close +"" + CrazyitProtocol.close);
        socket.close();
    }
    //向服务器发送要求下载文件用户的名字
    public void SetDownName(String filename)
    {
        ps.println(CrazyitProtocol.Down_Name + filename + CrazyitProtocol.Down_Name);
    }
    public static void main(String[] args) throws IOException {
        Client client = new Client(new ClientUI());
    }
}
package Client;

import Server.Server;
import UI.ClientUI;
import tool.CrazyitProtocol;

import javax.swing.*;
import java.io.*;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.Calendar;
/*
客户端线程类
 */
public class ClientThread extends Thread{
    BufferedReader br = null;
    ClientUI ui;
    public ClientThread(BufferedReader br,ClientUI ui)
    {
        this.br = br;
        this.ui = ui;
    }
    public void run(){
        try{
            String line = null;
            //不停读取服务器发回的消息
            while ((line = br.readLine()) != null)
            {
                //带有在线列表标识符的消息
                if(line.startsWith(CrazyitProtocol.UPDATE1)&&line.endsWith(CrazyitProtocol.UPDATE1))
                {
                    //对消息进行处理(去掉首尾的标识符)
                    String userNameList = line.substring(CrazyitProtocol.LONG,line.length()-CrazyitProtocol.LONG);
                    //获取在线人数
                    String number = userNameList.split(CrazyitProtocol.list_update)[0];
                    //转为int 类型
                    Integer sum = Integer.parseInt(number);
                    ui.num = sum;
                    ui.set_user_list_em();
                    //在UI界面将在线用户显示在用户列表里
                    for(int i = 0;i < sum;i++) {
                        ui.set_user_list(userNameList.split(CrazyitProtocol.list_update)[i+1] + "\n");
                        ui.strings[i] = userNameList.split(CrazyitProtocol.list_update)[i+1];
                    }
                }
                //带有文件列表更新标识符的消息
                else if(line.startsWith(CrazyitProtocol.DOWN_SIGN)&&line.endsWith(CrazyitProtocol.DOWN_SIGN))
                {
                    //同上
                    String fileNameList = line.substring(CrazyitProtocol.LONG,line.length()-CrazyitProtocol.LONG);
                    String number = fileNameList.split(CrazyitProtocol.list_update)[0];
                    Integer sum = Integer.parseInt(number);
                    ui.fileNum = sum;
                    //将文件列表存在UI界面的数组里,方便用JComboBox显示所有文件
                    for (int i = 0 ; i < sum ; i++)
                    {
                        ui.file_strings[i] = fileNameList.split(CrazyitProtocol.list_update)[i+1];
                    }
                }
                //带有文件下载标识符的消息
                else if(line.startsWith(CrazyitProtocol.Down_Name)&&line.endsWith(CrazyitProtocol.Down_Name))
                {
                    String filename = line.substring(CrazyitProtocol.LONG,line.length()-CrazyitProtocol.LONG);
                    DatagramSocket datagramSocket = new DatagramSocket(1211);
                    DatagramPacket datagramPacket = new DatagramPacket(new byte[1024*60],0,1024*60);
                    datagramSocket.receive(datagramPacket);
                    byte[] file = datagramPacket.getData();
                    FileOutputStream fileOutputStream  = new FileOutputStream(new File("D:\\updown\\"+filename));
                    fileOutputStream.write(file,0,file.length);
                    JOptionPane.showMessageDialog(null, "下载成功!");
                    datagramSocket.close();
                }
                //群聊消息
                else
                {
                    //每条消息都获取当前时间
                    Calendar cal=Calendar.getInstance();
                    int y=cal.get(Calendar.YEAR);
                    int m=cal.get(Calendar.MONTH);
                    m=m+1;//此时我的电脑上如果直接输出m会比真实时间小一个月,可能是自己电脑的问题,读者自行修改
                    int d=cal.get(Calendar.DATE);
                    int h=cal.get(Calendar.HOUR_OF_DAY);
                    int mi=cal.get(Calendar.MINUTE);
                    int s=cal.get(Calendar.SECOND);
                    ui.setTalk(y+":"+m+":"+d + "        " + h + ":" + mi + ":" + s);
                    ui.setTalk(line);
                }
            }
        } catch (SocketException e)
        {
        } catch (IOException e)
        {
            e.printStackTrace();
        } finally {
            try{
                if(br != null)
                    br.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}
package Server;

import tool.CrazyitMap;

import javax.swing.*;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketOption;
import java.util.ArrayList;

/*
服务器主类
 */
public class Server {
    private static final int SERVER_PORT = 1211;//端口号设置为1211
    public static CrazyitMap<String, PrintStream> clients = new CrazyitMap<>();
    public Server() throws IOException {
        init();
    }
    public void init() throws IOException {
        try(
                //开启ServerSocket
                ServerSocket ss = new ServerSocket(SERVER_PORT))
        {
            while (true)//死循环接收socket
            {
                Socket socket = ss.accept();
                new ServerThread(socket).start();//开启一个新线程
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        Server server = new Server();
    }
}
package Server;

import tool.CrazyitProtocol;

import javax.swing.*;
import java.io.*;
import java.net.*;

/*
服务器线程类
 */
public class ServerThread extends Thread{
    private Socket socket;
    BufferedReader br = null;
    PrintStream ps = null;
    public ServerThread(Socket socket)
    {
        this.socket=socket;
    }
    public void run() {
        try
        {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            ps = new PrintStream(socket.getOutputStream());
            String line = null;
            while ((line = br.readLine()) != null)//读取信息
            {
                //接收带有登录标识符的流
                if(line.startsWith(CrazyitProtocol.USER_ROUND) && line.endsWith(CrazyitProtocol.USER_ROUND))//如果带有登录的标识符 则进入重名的判断
                {

                    String username = getRealMsg(line);
                    //查重
                    //如果重复 发送带有重复标识符的消息
                    if(Server.clients.map.containsKey(username))
                    {
                        ps.println(CrazyitProtocol.NAME_REP);
                    }
                    //发送登录成功标识符的消息
                    else
                    {
                        ps.println(CrazyitProtocol.LOGIN_SUCCESS);
                        //用户集合里加入新登录的用户
                        Server.clients.put(username,ps);
                        for(var clients:Server.clients.valueSet())
                        {
                            clients.println(Server.clients.getkeyByValue(ps) + "进入聊天室");
                        }
                    }
                }
                //接收带有私聊标志的消息
                else if(line.startsWith(CrazyitProtocol.PRIVATE_ROUND)&&line.endsWith(CrazyitProtocol.PRIVATE_ROUND))//私聊标识符则进行私聊
                {
                    String userAndMsg = getRealMsg(line);
                    //得到要发送消息的用户名
                    String user = userAndMsg.split(CrazyitProtocol.SPLIT_SIGH)[0];
                    //得到要发送的消息
                    String msg = userAndMsg.split(CrazyitProtocol.SPLIT_SIGH)[1];
                    //发送私聊消息
                    Server.clients.map.get(user).println(Server.clients.getkeyByValue(ps) + "对你耳语:" + msg);
                }
                //接收带有用户列表更新标识符的消息
                else if(line.startsWith(CrazyitProtocol.UPDATE1)&&line.endsWith(CrazyitProtocol.UPDATE1))
                {
                    //获取在线用户的个数
                    Integer sumName = Server.clients.map.size();
                    String userNameList = CrazyitProtocol.UPDATE1 + sumName.toString();
                    for(String name : Server.clients.map.keySet()) {
                        userNameList += CrazyitProtocol.list_update + name;
                    }
                    userNameList += CrazyitProtocol.UPDATE1;
                    for(PrintStream clientPS : Server.clients.valueSet()) {//通过map遍历输出流,向全体客户端发送消息
                        clientPS.println(userNameList);
                    }
                }
                //接收带有关闭标识符的消息
                else if(line.startsWith(CrazyitProtocol.close) && line.endsWith(CrazyitProtocol.close))
                {
                    String name = Server.clients.getkeyByValue(ps);
                    for(PrintStream clientPS : Server.clients.valueSet()) {//通过map遍历输出流,向全体客户端发送消息
                        clientPS.println(name + " 离开了 ");
                    }
                    //在线用户列表移除此用户
                    Server.clients.removeByValue(ps);
                    Integer sumName = Server.clients.map.size();
                    //更新所有用户的在线用户列表
                    String userNameList = CrazyitProtocol.UPDATE1 + sumName.toString();
                    for(String name1 : Server.clients.map.keySet()) {
                        userNameList += CrazyitProtocol.list_update + name1;
                    }
                    userNameList += CrazyitProtocol.UPDATE1;
                    for(PrintStream clientPS : Server.clients.valueSet()) {//通过map遍历输出流,向全体客户端发送消息
                        clientPS.println(userNameList);
                    }
                }
                //接收带有上传文件标识符的消息
                else if(line.startsWith(CrazyitProtocol.FILE_ROUND)&&line.endsWith(CrazyitProtocol.FILE_ROUND))
                {
                    //获取文件名
                    String filename = getRealMsg(line);
                    DatagramSocket datagramSocket = new DatagramSocket(1211);
                    DatagramPacket datagramPacket = new DatagramPacket(new byte[1024*60],0,1024*60);
                    datagramSocket.receive(datagramPacket);
                    byte[] file = datagramPacket.getData();
                    FileOutputStream fileOutputStream  = new FileOutputStream(new File("D:\\upload\\"+filename));
                    fileOutputStream.write(file,0,file.length);
                    RandomAccessFile randomAccessFile = new RandomAccessFile("src\\FileNameList.txt","rw");
                    randomAccessFile.seek(randomAccessFile.length());
                    randomAccessFile.write(( CrazyitProtocol.list_update + filename).getBytes());
                    datagramSocket.close();
                }
                //接收带有文件列表更新标识符的消息
                else if(line.startsWith(CrazyitProtocol.DOWN_SIGN)&&line.endsWith(CrazyitProtocol.DOWN_SIGN)) {
                    File file = new File("src\\FileNameList.txt");
                    RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
                    byte[] bytes = new byte[(int) file.length()];
                    randomAccessFile.read(bytes);
                    randomAccessFile.close();
                    String fileName = new String(bytes);
                    Integer sum = 0;
                    String str = fileName;
                    while (str.indexOf(CrazyitProtocol.list_update) != -1) {
                        str = str.substring(str.indexOf(CrazyitProtocol.list_update) + 1, str.length());
                        sum++;
                    }
                    for (PrintStream clientPS : Server.clients.valueSet()) {//通过map遍历输出流,向全体客户端发送消息
                        clientPS.println(CrazyitProtocol.DOWN_SIGN + sum.toString() + fileName + CrazyitProtocol.DOWN_SIGN);
                    }
                }
                //群聊
                else if(line.startsWith(CrazyitProtocol.MSG_ROUND)&&line.endsWith(CrazyitProtocol.MSG_ROUND))//群聊
                {
                    String msg = getRealMsg(line);
                    for(var clients:Server.clients.valueSet())
                    {
                        clients.println(Server.clients.getkeyByValue(ps) + ":  " + msg);
                    }
                }
                //带有文件下载标识符的消息
                else if(line.startsWith(CrazyitProtocol.Down_Name)&&line.endsWith(CrazyitProtocol.Down_Name))
                {
                    String filename = getRealMsg(line);
                    ps.println(CrazyitProtocol.Down_Name + filename + CrazyitProtocol.Down_Name);
                    DatagramSocket datagramSocket = null;
                    try {
                        datagramSocket = new DatagramSocket(1210);
                    } catch (SocketException socketException) {
                        socketException.printStackTrace();
                    }
                    //创建文件输入流,读取本地文件
                    FileInputStream fileInputStream = null;
                    try {
                        fileInputStream = new FileInputStream(new File("D:\\upload\\" + filename));
                    } catch (FileNotFoundException fileNotFoundException) {
                        fileNotFoundException.printStackTrace();
                    }
                    //读取输入流中的数据
                    byte[] bytes = new byte[0];//创建数组
                    try {
                        bytes = new byte[fileInputStream.available()];
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                    try {
                        fileInputStream.read(bytes);//给数组写入数据
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                    //创建数据载体DatagramPacket
                    DatagramPacket datagramPacket = null;
                    try {
                        datagramPacket = new DatagramPacket(bytes, 0, bytes.length, InetAddress.getByName("127.0.0.1"), 1211);
                    } catch (UnknownHostException unknownHostException) {
                        unknownHostException.printStackTrace();
                    }
                    //发送
                    try {
                        datagramSocket.send(datagramPacket);
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                    if (fileInputStream != null) {
                        try {
                            fileInputStream.close();
                        } catch (IOException ioException) {
                            ioException.printStackTrace();
                        }
                    }
                    //成功上传,弹框
                    datagramSocket.close();
                }
                else {
                }
            }
        } catch (SocketException e) {
            try
            {
                if(br != null)
                {
                    br.close();
                }
                if(ps != null)
                {
                    ps.close();
                }
                if(socket != null)
                {
                    socket.close();
                }
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    private String getRealMsg(String line)//去掉标识符,获取真实信息
    {
        return line.substring(CrazyitProtocol.LONG,line.length() - CrazyitProtocol.LONG);
    }
}
package UI;

import Client.Client;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;

/*
客户端的UI页面
 */
public class ClientUI extends Thread{
    private final JFrame jFrame = new JFrame("麦爱思聊天室");
    private final Font font1 = new Font("微软雅黑",1,18);
    private final Font font2 = new Font("华文隶书",1,25);
    private final Font font3 = new Font("华文楷体",1,18);
    public JTextField nameJT;
    public JTextArea user_list_Vis;
    public JTextArea talkJT;
    public JTextField message;
    public Client client1;
    public String name1;
    public  String[] strings = new String[9999];
    public String[] file_strings = new String[9999];
    public int num;
    public int fileNum;
    public String DownName;
    public  boolean flag=false;
    private final Toolkit toolkit = Toolkit.getDefaultToolkit();
    public void run()
    {
        //设置空布局管理器,设置JFrame的大小并居中
        jFrame.setLayout(null);
        jFrame.setBounds((toolkit.getScreenSize().width - 850) / 2, (toolkit.getScreenSize().height - 620) / 2, 850, 620);
        JPanel jPanel0 = new JPanel(null);
        jPanel0.setBounds(0,0,850,60);
        jPanel0.setBorder(BorderFactory.createEtchedBorder());
        jFrame.add(jPanel0);
        JLabel name  = new JLabel();
        name.setFont(font1);
        name.setText("登录名");
        name.setBounds(25,10,60,30);
        jPanel0.add(name);
        nameJT = new JTextField();
        nameJT.setText("");
        nameJT.setFont(font1);
        nameJT.setBorder(BorderFactory.createLoweredBevelBorder());
        nameJT.setBounds(85,10,100,35);
        jPanel0.add(nameJT);
        JLabel server_ip = new JLabel();
        server_ip.setText("服务器ip");
        server_ip.setFont(font1);
        server_ip.setBounds(200,10,80,30);
        jPanel0.add(server_ip);
        JTextField server_ipJT = new JTextField();
        server_ipJT.setText("127.0.0.1");
        server_ipJT.setFont(font1);
        server_ipJT.setBounds(280,10,100,35);
        server_ipJT.setBorder(BorderFactory.createEtchedBorder());
        server_ipJT.setEditable(false);
        jPanel0.add(server_ipJT);
        JLabel port = new JLabel();
        port.setFont(font1);
        port.setText("服务器端口");
        port.setBounds(380,10,100,35);
        jPanel0.add(port);
        JTextField portJT = new JTextField();
        portJT.setEditable(false);
        portJT.setFont(font1);
        portJT.setText("   1211");
        portJT.setBounds(490,10,100,35);
        portJT.setBorder(BorderFactory.createEtchedBorder());
        jPanel0.add(portJT);
        JButton connect = new JButton("连接服务器");
        connect.setBounds(600,10,130,35);
        connect.setFont(font3);
        jPanel0.add(connect);
        JButton cls = new JButton("清屏");
        cls.addActionListener(e -> {
            if(client1 == null)
            {
                JOptionPane.showMessageDialog(jFrame,"还未进行网络连接!");
                return;
            }
            talkJT.setText("");
        });
        cls.setFont(font3);
        cls.setBounds(740,10,90,35);
        jPanel0.add(cls);
        JPanel user_list = new JPanel(null);
        user_list.setBorder(BorderFactory.createEtchedBorder());
        user_list.setBounds(0,60,200,460);
        jFrame.add(user_list);
        JLabel online_user = new JLabel();
        online_user.setBounds(0,0,200,60);
        online_user.setBorder(BorderFactory.createEtchedBorder());
        online_user.setText("     用户列表");
        online_user.setFont(font2);
        user_list.add(online_user);
        user_list_Vis = new JTextArea();
        user_list_Vis.setEditable(false);
        user_list_Vis.setFont(font3);
        user_list_Vis.setLineWrap(true);
        user_list_Vis.setWrapStyleWord(true);
        user_list_Vis.setText("");
        user_list_Vis.setBounds(0,60,200,340);
        user_list.add(user_list_Vis);
        JButton get_new_list = new JButton("私聊");
        get_new_list.setBounds(20,410,80,30);
        get_new_list.setFont(font3);
        user_list.add(get_new_list);
        get_new_list.addActionListener(e -> {
            private_choose private_choose = new private_choose(this);
        });
        JButton down = new JButton("下载");
        down.setBounds(105,410,80,30);
        down.setFont(font3);
        user_list.add(down);
        down.addActionListener(e -> {
            if(client1==null)
            {
                JOptionPane.showMessageDialog(jFrame,"还未进行网络连接!");
                return;
            }
            if (flag==false)
            {
                {
                    JOptionPane.showMessageDialog(jFrame,"请先选择文件!!");
                    return;
                }
            }
            client1.SetDownName(DownName);
            flag=false;
        });
        JPanel talk = new JPanel(null);
        talk.setBounds(200,60,650,460);
        talk.setBorder(BorderFactory.createEtchedBorder());
        jFrame.add(talk);
        talkJT = new JTextArea();
        talkJT.setFont(font3);
        talkJT.setBounds(0,0,650,460);
        talkJT.setBorder(BorderFactory.createEtchedBorder());
        talkJT.setEditable(false);
        talkJT.setLineWrap(true);
        talkJT.setWrapStyleWord(true);
        talk.add(talkJT);
        JPanel message_area = new JPanel(null);
        message_area.setBounds(0,520,850,70);
        message_area.setBorder(BorderFactory.createEtchedBorder());
        jFrame.add(message_area);
        message = new JTextField();
        message.setText("");
        message.setFont(font3);
        message.setBounds(10,15,450,30);
        message.setBorder(BorderFactory.createLoweredBevelBorder());
        message_area.add(message);
        JButton send = new JButton("发送信息");
        send.setFont(font3);
        send.setBounds(470,15,110,30);
        message_area.add(send);
        JButton download = new JButton("选择文件");
        download.addActionListener(e -> {
            if(client1==null)
            {
                JOptionPane.showMessageDialog(jFrame,"还未进行网络连接!");
                return;
            }
            File_Down_Choose file_down_choose = new File_Down_Choose(this);
        });
        download.setFont(font3);
        download.setBounds(590,15,110,30);
        message_area.add(download);
        JButton upload = new JButton("上传文件");
        upload.addActionListener(e -> {
            if(client1==null)
            {
                JOptionPane.showMessageDialog(jFrame,"还未进行网络连接!");
                return;
            }
            try {
                client1.UpDate();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        });
        upload.setFont(font3);
        upload.setBounds(710,15,110,30);
        message_area.add(upload);
        jFrame.setVisible(true);
        nameJT.addKeyListener((new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {
                String s = nameJT.getText();
                if(s.length()>7)
                    e.consume();
            }
            @Override
            public void keyPressed(KeyEvent e) {
                // TODO Auto-generated method stub
            }

            @Override
            public void keyReleased(KeyEvent e) {
                // TODO Auto-generated method stub
            }
        }));
        send.addActionListener(e -> {
            if (client1 == null)
            {
                JOptionPane.showMessageDialog(jFrame,"还未进行网络连接!");
                return;
            }
            client1.readAndSend();
        });
        connect.addActionListener(e -> {
            try {
                if(name1 != nameJT.getText())
                {
                    Client client = new Client(this);
                    client1 = client;
                    return;
                }
                if(client1 != null)
                {
                    JOptionPane.showMessageDialog(jFrame,"已经连接到服务器!");
                    return;
                }
                Client client = new Client(this);
                client1 = client;
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        });
        name1 = nameJT.getText();
        jFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                if (client1==null)
                {
                    jFrame.dispose();
                    return;
                }
                try {
                    client1.close();
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
        });
    }
    //获取nameJT的内容
    public String getNameJT()
    {
        String name = nameJT.getText();
        return name;
    }
    //连接服务器成功后设置nameJT为不可编辑的
    public void setNameJTEdit()
    {
        nameJT.setEditable(false);
    }
    //在talkJT里输出内容
    public void setTalk(String str)
    {
        talkJT.append(str + "\n");
    }
    //获取message内容
    public String getMsg()
    {
        return message.getText();
    }
    //消息显示在聊天区域里
    public void setMsg(String str)
    {
        message.setText(str);
    }
    //弹出提示框
    public void new_Msg(String str)
    {
        JOptionPane.showMessageDialog(jFrame,str);
    }
    //用户列表的显示
    public void set_user_list(String str)
    {
        user_list_Vis.append(str);
    }
    //用户列表的清空
    public void set_user_list_em(){ user_list_Vis.setText("");}
    public void setGetDoWn(String str)
    {
        DownName = str;
    }
    public static void main(String[] args) throws IOException {
        ClientUI clientUI = new ClientUI();
    }
 }

这里是完整项目的下载地址:点这里下载
下载项目的读者请注意:
1.本项目使用IDEA完成,请在IDEA里打开;
2.如果不能打开,可以在下载解压好的文件里找到src文件夹,在此文件夹里用记事本打开.java程序查看类的代码。

码字不易,如果你觉得此博客对你有用,就一键三连吧!

本文地址:https://blog.csdn.net/luyuan492/article/details/107433466

《2020暑假集训项目——Java简易聊天室.doc》

下载本文的Word格式文档,以方便收藏与打印。