欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java 综合应用程序的开发(多人聊天室)

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

一、 实验目的
熟悉 Java 综合应用程序的开发。
二、 实验任务

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

客户端代码 ( ClientChat.java)

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.util.*;

public class ClientChat extends JFrame {   //客户端窗口

    private JTextArea jTextArea = new JTextArea(10,20);  //文本区域
    private JScrollPane jScrollPane = new JScrollPane(jTextArea);  //为文本区域加滚动条

    private JTextField jTextField = new JTextField(20);   //输入文本框
    private static final String CONNSTR = "127.0.0.1";
    private static final int CONNPORT = 8888; //服务器端口号
    private Socket socket = null;

    private DataOutputStream dataOutputStream = null;  //设置一个管子

    private boolean isConn = false;

    public ClientChat() throws  HeadlessException{
        super();
    }

    public void init(String name){
        this.setTitle("欢迎使用"+name+"聊天室应用");
        this.add(jScrollPane, BorderLayout.CENTER);  //把文本区放在中间
        this.add(jTextField,BorderLayout.SOUTH);  //把输入文本框放在南边
        this.setBounds(300,300,550,400);  //设计大小
        jTextField.addActionListener(new ActionListener() {  //对文本区设计一个监听
            @Override
            public void actionPerformed(ActionEvent e) {
                String strSend = jTextField.getText();
                //strSend发送到服务器上

                if(strSend.trim().length() == 0){  //如果去掉两头空格长度等于0表明为空不能输出
                    return;
                }
                send(strSend);

                jTextField.setText("");  //写完后消失(等于变成空字符串)
                //jTextArea.append(strSend+'\n');  //往文本区添加输入的内容和换行

            }
        });

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  //点击关闭按钮关闭程序
        jTextArea.setEditable(false);  //设计文本区域不能编辑
        jTextField.requestFocus();  //光标聚焦在输入文本框

        try {   //处理抛出异常
            socket = new  Socket(CONNSTR,CONNPORT);
            isConn = true;  //表示连上服务器

        } catch (IOException e) {
            e.printStackTrace();
        }

        this.setVisible(true);  //可视

        Thread thread = new Thread(new Receive());   //改了
        thread.setName(name);
        thread.start(); //启动客户端多线程
    }

    //发送信息到服务器上的方法
    public void send(String str){
        try{
            dataOutputStream = new DataOutputStream(socket.getOutputStream());
            dataOutputStream.writeUTF(str);
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    //多线程类,实现了Runnable接口
    class Receive implements Runnable{

        @Override
        public void run() {
            try {
                while(isConn) {
                    DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
                    String str = dataInputStream.readUTF();
                    jTextArea.append(str);
                }
            } catch (SocketException e) {
               System.out.println("服务器中断!!!");
               jTextArea.append("服务器中断!! \n");
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String []args){
        Scanner input = new Scanner(System.in);
        System.out.println("请输入你的昵称例如(网络191张飞龙)");
        String name = input.nextLine();
        ClientChat clientChat = new ClientChat();
        clientChat.init(name);
    }
}

服务端代码 ( ServerChat.java)

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Iterator;

public class ServerChat extends JFrame {     //服务端(基于TCP的socket编程)
    private static final int PORT = 8888;  //设计一个端口常量
    private JTextArea jTextArea = new JTextArea();  //文本区(用于显示客户端显示连接)
    private JScrollPane jScrollPane = new JScrollPane(jTextArea);  //为文本区域加滚动条
    private JPanel jPanel = new JPanel();   //设置一个面板方便放置两个按钮
    private JButton jButton1 = new JButton("启动");  //两个按钮(启动,停止)
    private JButton jButton2 = new JButton("停止");

    private ServerSocket serverSocket = null;

    private ArrayList<ClientConn> ccList = new ArrayList<ClientConn>();  //创建一个线程数组

    private boolean isStart = false;  //用于判断是否启动

    public ServerChat(){
        this.setTitle("服务器端");
        this.add(jScrollPane, BorderLayout.CENTER);  //文本区放中间

        jPanel.add(jButton1);
        jPanel.add(jButton2);
        this.add(jPanel,BorderLayout.SOUTH);  //把两个按钮放在南边(FlowLayout布局)

        this.setBounds(0,0,500,500);

        if(isStart){
            jTextArea.append("服务器已经启动了!  \\n");
        }else {
            jTextArea.append("服务器还没启动,请点击启动按钮!  \\n\\n");
        }

        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                isStart = false;
                try {
                    if(serverSocket != null){
                        serverSocket.close();
                    }
                    System.out.println("服务器停止!");
                    jTextArea.append("服务器断开!");
                    System.exit(0);
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
        });

        jButton2.addActionListener(new ActionListener() {  //为停止按钮设计监听
            @Override
            public void actionPerformed(ActionEvent e) {
                isStart = false;
                try {
                    if(serverSocket != null){
                        serverSocket.close();
                        isStart = false;
                    }
                    System.exit(0);
                    jTextArea.append("服务器断开!");
                    System.out.println("服务器停止!");
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }

            }
        });

        jButton1.addActionListener(new ActionListener() {  //为启动按钮设计监听
            @Override
            public void actionPerformed(ActionEvent e) {   //处理startServer()方法抛出的异常
                System.out.println("hhhh");

                try{
                    //isStart = true; //标置启动了
                    if(serverSocket == null){
                        serverSocket = new ServerSocket(PORT);
                    }

                    isStart = true;
                    jTextArea.append("服务器已经启动!"+"\n");
                }catch (IOException e1){
                    e1.printStackTrace();
                }
            }
        });
        this.setVisible(true);
        startServer();

    }

    //服务器的启动方法
    public void startServer() {

        try{
            try{
                serverSocket = new ServerSocket(PORT);
                isStart = true;
            }catch (IOException e2){
                e2.printStackTrace();
            }
            //可以接收多个客户端的连接
            while(isStart) {
                Socket socket = serverSocket.accept();
                ccList.add(new ClientConn(socket));
                System.out.println("一个客户端连接服务器:" + socket.getInetAddress() + "/" + socket.getPort());
                jTextArea.append("一个客户端连接服务器:" + socket.getInetAddress() + "/" + socket.getPort()+"\n");
            }

            //reciveStr();
        }catch (SocketException e){
            System.out.println("服务器中断!!!");
        }
        catch (IOException e){
            e.printStackTrace();
        }


    }

    //这个对象是属于服务器端的一个连接对象
    class ClientConn implements Runnable{
        Socket socket = null;
        public ClientConn(Socket socket){  //把连接传过来
            this.socket = socket;
            (new Thread(this)).start();  //启动线程
        }

        //对于客户端应该是多线程的(同时接收客户端信息的)-多线程接收数据
        public void run(){   //重写run()方法
            try {
                DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());  //设置一条管子
                //为了让服务器能够接收到每个客户端的多条信息
                while(isStart) {

                    String str = dataInputStream.readUTF();

                    System.out.println(socket.getInetAddress()+"|"+socket.getPort()+"说:"+str + "\n");
                    jTextArea.append(socket.getInetAddress()+"|"+socket.getPort()+"说:"+str + "\n");
                    String strSend =socket.getInetAddress()+"|"+socket.getPort()+"说:"+str + "\n";
                    //需要遍历ccList,调用send()方法,在客户端接受信息也是多线程接受
                    Iterator<ClientConn> it = ccList.iterator();
                    while(it.hasNext()){
                        ClientConn o = it.next();
                        o.send(strSend);
                    }
                }

            } catch (SocketException e) {
               System.out.println("一个客户端下线了");
               jTextArea.append(socket.getInetAddress()+"|"+socket.getPort()+"客户端下线了");
            }
            catch (IOException e) {
                e.printStackTrace();
            }

        }
        //每个连接对象发送数据的方法
        public void send(String str){
            try {
                DataOutputStream dataOutputStream = new DataOutputStream(this.socket.getOutputStream());
                dataOutputStream.writeUTF(str);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String []args){
        ServerChat serverChat = new ServerChat();
    }
}

1.先运行服务端代码(ServerChat.java)并点击启动按钮
Java 综合应用程序的开发(多人聊天室)

2.多次运行客户端代码(ClientChat.java)这次以运行三次为例,每运行一次代码就创建一个线程。(先在控制台输入名称,才弹出窗口)
Java 综合应用程序的开发(多人聊天室)
Java 综合应用程序的开发(多人聊天室)
Java 综合应用程序的开发(多人聊天室)
Java 综合应用程序的开发(多人聊天室)
Java 综合应用程序的开发(多人聊天室)
3.发送信息检测代码
Java 综合应用程序的开发(多人聊天室)
4 .关闭客户端窗口退出该线程,剩下的人还能说话
Java 综合应用程序的开发(多人聊天室)
5.停止服务端
Java 综合应用程序的开发(多人聊天室)

本文地址:https://blog.csdn.net/weixin_49035831/article/details/111935219