合工大Java实验三Java---基于GUI的网络通信程序设计

本实验代码说明:

本实验代码在 vscode1.63.1上运行实证吗,没有问题,且GUI界面完全仿照实验要求报告制作

本代码的Java环境为Java 11.06,并非教学时使用的Java 8 还请注意

本代码运行时请先优先运行server端,设置合适端口,再运行client端,但请注意本代码仍有bug,受限于本人时间与精力没有解决(当前代码只能实现单server对预先代码中设置的client数量连接,且在没有连接足够的客户端时,GUI线程会阻塞),注意,注意。

运行前记得改包名

Server端:

package experiment.experiment3;

import java.awt.*;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.border.TitledBorder;

public class Server {

    public static void main(String args[]) {
        Myframe frame = new Myframe();
        password passwordFrame = new password();
        passwordFrame.UI(frame);
        frame.UI();

    }

}

class password extends Frame {

    private static final String PASSWORD = "2021218999";                    //登录密码,写死了

    private Toolkit kit = Toolkit.getDefaultToolkit();                      // 获取工具包
    private Dimension screenSize = kit.getScreenSize();                     // 获取窗体宽高,并将其赋值给screenSize封装

    private Frame MainFrame = new Frame("登录");                        // 主窗口

    private JPanel passwordJPanel = new JPanel();                               // 组装用JPanel
    private TitledBorder passwordBorder = new TitledBorder("输入密码:");       // 标题
    private static Font defaultFont = new Font("SimSun", Font.PLAIN, 12);       // 默认字体
    private Box passwordBox = Box.createHorizontalBox();                            // 密码输入组件组装box
    private JLabel passwordJLabel = new JLabel("密码:");                   // 密码输入提示
    private Button passwordButton = new Button("确认");                     // 密码输入确认按钮
    private TextField passworTextField = new TextField(20);              // 密码输入框

    public void UI(Myframe frame) {
        int screenWidth = screenSize.width; // 获取屏幕的宽
        int screenHeight = screenSize.height; // 获取屏幕的高
        int windowWidth = 400; // 获得窗口宽
        int windowHeight = 100;// 获得窗口高
        MainFrame.setSize(new Dimension(windowWidth, windowHeight)); // 设置窗口大小
        MainFrame.setLocation(screenWidth / 2 - windowWidth / 2, screenHeight / 2 - windowHeight / 2); // 设置窗体位置

        passworTextField.setEchoChar('*');                          //设置密码回显字符,输入密码显示“*”
        
        // 窗体组装
        passwordBox.add(passwordJLabel);
        passwordBox.add(passworTextField);
        passwordBox.add(passwordButton);
        passwordBorder.setTitleFont(defaultFont);
        passwordJPanel.setBorder(passwordBorder);
        passwordJPanel.add(passwordBox);
        MainFrame.add(passwordJPanel);

        // 给主窗体添加事件侦听器,使其可以关闭
        MainFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        // 给按钮的添加事件侦听器,其作用如下:当文本输入框输入的文本和预设的密码一致,则使密码输入窗口消失,同时使用MyFrame类中的setShow方法,使MyFrame的frame对象显示
        passwordButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String password;
                try {
                    password = passworTextField.getText();
                    if (password.equals(PASSWORD)) {
                        MainFrame.dispose();
                        frame.setShow();
                    }
                } catch (Exception er) {
                    er.printStackTrace();
                }
            }
        });

        MainFrame.setVisible(true);
    }

}

class Myframe extends Frame {
    private Toolkit kit = Toolkit.getDefaultToolkit(); // 获取工具包
    private Dimension screenSize = kit.getScreenSize(); // 获取窗体宽高,并将其赋值给screenSize封装

    // 主窗体
    private Frame MainFrame = new Frame("服务端"); // 主窗口

    // 端口设置窗体
    private JPanel PortPanel = new JPanel();
    private TitledBorder titledBorder1 = new TitledBorder("服务器设置"); // 端口设置带边框标题的输入框
    private Box PortBox = Box.createHorizontalBox(); // Box容器,组装服务器设置输入框
    private Label PortLabel = new Label("端口号:"); // 端口输入框提示文本
    private TextField portTextField = new TextField(5); // 端口输入框,同时由于Windows的端口号最大为65535所以设置输入框最大输入列为5
    private Button connecButton = new Button("确认"); // 端口输入确认按钮
    private static Font defaultFont = new Font("SimSun", Font.PLAIN, 12); // 默认字体

    // 消息显示窗体
    private JPanel messageJPanel = new JPanel();
    private TextArea messageArea = new TextArea(60, 90); // 聊天文本框,显示聊天记录

    // 消息输入窗体
    private JPanel sayJPanel = new JPanel();
    private Box sayBox = Box.createHorizontalBox(); // box容器,组装发言输入框
    private TextField sayTextField = new TextField(90); // 发言输入框,输入要发出的内容
    private Button sayButton = new Button("发送"); // 发言确认按钮

    public static List<Socket> socketList = new ArrayList<Socket>();
    // 窗体组装方法
    public void UI() {
        int screenWidth = screenSize.width; // 获取屏幕的宽
        int screenHeight = screenSize.height; // 获取屏幕的高
        int windowWidth = 800; // 获得窗口宽
        int windowHeight = 600;// 获得窗口高
        MainFrame.setSize(new Dimension(windowWidth, windowHeight)); // 设置窗口大小
        MainFrame.setLocation(screenWidth / 2 - windowWidth / 2, screenHeight / 2 - windowHeight / 2); // 设置窗体位置

        // 服务器端口设置框体组装
        PortBox.add(PortLabel);
        PortBox.add(portTextField);
        PortBox.add(connecButton);
        titledBorder1.setTitleFont(defaultFont); // 设置边框字体
        PortPanel.setBorder(titledBorder1); // 为JPanel容器添加边框
        PortPanel.add(PortBox); // 将端口组件组装盒子放入JPanel
        MainFrame.add(PortPanel, BorderLayout.NORTH); // 将Panel添加到主窗体中

        // 消息显示窗体组装
        messageJPanel.add(messageArea); // 将消息框放入对应的JPanel容器
        MainFrame.add(messageJPanel, BorderLayout.CENTER); // 将消息对应的JPanel容器放入主窗体

        // 消息发送窗体组装
        sayBox.add(sayTextField); // 将消息输入框放入对应的Box容器
        sayBox.add(sayButton); // 将消息发送按钮放入对应的box容器
        sayJPanel.add(sayBox); // 将box容器放入对应的JPanel中
        MainFrame.add(sayJPanel, BorderLayout.SOUTH); // 将JPanel放入主窗体的下方
        
        ServerHandler serverHandler = new ServerHandler(socketList);

        // 端口连接按钮添加事件侦听器,当按钮按下时,开始持续监听来自客户端的请求
        connecButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    //建立serversokcet
                    ServerSocket serverSocket = new ServerSocket(Integer.parseInt(portTextField.getText()));
                    Socket socket = null;
                    messageArea.setText("Server starting…\n");
                    int i=2;        //最大客户端数量
                    while(i>0)
                    {  
                        i--;
                        socket = serverSocket.accept();
                        socketList.add(socket);
                        new Thread(new Task(socket,messageArea)).start();
                    }
                } catch (Exception er) {
                    er.printStackTrace();
                }
            }
        });

        //给发言按钮添加事件侦听器,当按下后,按钮发送消息
        sayButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                serverHandler.SendMessage(sayTextField.getText());
                messageArea.append("服务器:"+sayTextField.getText());
                sayTextField.setText("");
            }
        });
        // 给主窗体添加事件侦听器,使其可以关闭
        MainFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }

    // 方法:设置窗口可见
    public void setShow() {
        MainFrame.setVisible(true);
    }
}

//Task类,实现Runnable接口
class Task implements Runnable{
    private Socket socket = null;               //存储socket
    private TextArea messageArea = null;        //存储显示模块

    //构造方法;
    //获取套接字和消息显示框
    public Task(Socket socket,TextArea messageArea)
    {
        this.socket =socket;
        this.messageArea = messageArea; 
    }

    @Override 
    public void run()
    {
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (true) {
                String message = bufferedReader.readLine();
                //接受同时发送
                for(Socket item : Myframe.socketList)
                {
                    PrintWriter printWriter = new PrintWriter(item.getOutputStream());      
                    printWriter.write(message+"\n");
                    messageArea.append(message+"\n");
                    printWriter.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
}

//服务器发言部分的处理
class ServerHandler{

    private List<Socket>socketList = new ArrayList<Socket>();

    public ServerHandler(List<Socket>soketList)
    {
        this.socketList = soketList;
    }

    public void SendMessage(String message)
    {
        for(Socket item : socketList)
        try {

            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(item.getOutputStream()));
            bufferedWriter.write("服务器:"+message+"\n");
            bufferedWriter.flush();

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

Client端:

package experiment.experiment3;
import java.awt.*;
import javax.swing.Box;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;

public class Client {
    public static void main(String args[])
    {
        UserName usn = new UserName();
        ClientFrame frame = new ClientFrame();
        usn.UI(frame);
        frame.UI();
    }
}

//用户名输入相关类
class UserName extends Frame {
    private Toolkit kit = Toolkit.getDefaultToolkit(); // 获取工具包
    private Dimension screenSize = kit.getScreenSize(); // 获取窗体宽高,并将其赋值给screenSize封装

    private static Font defaultFont = new Font("SimSun", Font.PLAIN, 12); // 默认字体
    private Frame MainFrame = new Frame("昵称输入");                              //主窗体
    private JPanel titlePanel  = new JPanel();                                          //主Jpanel
    private TitledBorder titledBorder = new TitledBorder("输入用户名:");          //边框
    private Box titleBox = Box.createHorizontalBox();                                   //组装用Box
    private TextField tf = new TextField(15);                                   //昵称输入框,限制输入字符15个
    private Button btn = new Button("确认");                                    //确认按钮

    private String UserName;                                                //用户名

    public void UI(ClientFrame frame)
    {
        int screenWidth = screenSize.width; // 获取屏幕的宽
        int screenHeight = screenSize.height; // 获取屏幕的高
        int windowWidth = 400; // 获得窗口宽
        int windowHeight = 100;// 获得窗口高
        MainFrame.setSize(new Dimension(windowWidth, windowHeight)); // 设置窗口大小
        MainFrame.setLocation(screenWidth / 2 - windowWidth / 2, screenHeight / 2 - windowHeight / 2); // 设置窗体位置

        titleBox.add(tf);
        titleBox.add(btn);
        titledBorder.setTitleFont(defaultFont);
        titlePanel.setBorder(titledBorder);
        titlePanel.add(titleBox);
        MainFrame.add(titlePanel);

        //给按钮添加事件侦听器,当按钮按下后,首先将文本框内的文本赋值给UserName,然后关闭用户名输入窗口,同时打开聊天窗口
        btn.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e)
            {
                try {
                    UserName = tf.getText();
                    frame.GetUserName(UserName);
                    MainFrame.dispose();                        //用户名输入窗口隐藏
                    frame.setShow();                            //聊天窗口显示
                } catch (Exception er) {
                    er.printStackTrace();
                }
            }
        });

        MainFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        MainFrame.setVisible(true);
    }

    public String GetName()
    {
        return UserName;
    }

}

//客户端界面相关类
class ClientFrame extends Frame {
    private Toolkit kit = Toolkit.getDefaultToolkit();                                  // 获取工具包
    private Dimension screenSize = kit.getScreenSize();                                 // 获取窗体宽高,并将其赋值给screenSize封装
    private static Font defaultFont = new Font("SimSun", Font.PLAIN, 12); // 默认字体

    //客户端设置窗体
    private Frame MainFrame = new Frame();
    private TitledBorder titledBorder = new TitledBorder("客户端设置:");
    private JPanel titleJPanel = new JPanel();
    private Box titlebBox = Box.createHorizontalBox();
    private Label lb_ip = new Label("服务器IP:");
    private TextField tf_Ip = new TextField(15);
    private Label lb_port = new Label("端口:");
    private TextField tf_port = new TextField(5);
    private Button btn_title = new Button("连接");

    // 消息显示窗体
    private JPanel messageJPanel = new JPanel();                            //容器
    private TextArea messageArea = new TextArea(60, 90);    //聊天文本框,显示聊天记录

     // 消息输入窗体
    private JPanel sayJPanel = new JPanel();
    private Box sayBox = Box.createHorizontalBox();                     //box容器,组装发言输入框
    private TextField sayTextField = new TextField(90);         //发言输入框,输入要发出的内容
    private Button sayButton = new Button("发送");              //发言确认按钮

    private String UserName;                                        //用户名
    public void GetUserName(String UserName)                             //从上一个窗口获得用户名
    {   
        this.UserName = UserName;
    }

    public void UI()
    {
        int screenWidth = screenSize.width; // 获取屏幕的宽
        int screenHeight = screenSize.height; // 获取屏幕的高
        int windowWidth = 800; // 获得窗口宽
        int windowHeight = 600;// 获得窗口高
        MainFrame.setSize(new Dimension(windowWidth, windowHeight)); // 设置窗口大小
        MainFrame.setLocation(screenWidth / 2 - windowWidth / 2, screenHeight / 2 - windowHeight / 2); // 设置窗体位置

        titlebBox.add(lb_ip);
        titlebBox.add(tf_Ip);
        titlebBox.add(Box.createHorizontalStrut(100));
        titlebBox.add(lb_port);
        titlebBox.add(tf_port);
        titlebBox.add(Box.createHorizontalStrut(100));
        titlebBox.add(btn_title);
        titledBorder.setTitleFont(defaultFont);
        titleJPanel.setBorder(titledBorder);
        titleJPanel.add(titlebBox);
        MainFrame.add(titleJPanel,BorderLayout.NORTH);

        messageJPanel.add(messageArea);
        MainFrame.add(messageJPanel,BorderLayout.CENTER);

        // 消息发送窗体组装
        sayBox.add(sayTextField); // 将消息输入框放入对应的Box容器
        sayBox.add(sayButton); // 将消息发送按钮放入对应的box容器
        sayJPanel.add(sayBox); // 将box容器放入对应的JPanel中
        MainFrame.add(sayJPanel, BorderLayout.SOUTH); // 将JPanel放入主窗体的下方

        Handler handler = new Handler();

        btn_title.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                try {
                    messageArea.append("Connect to server…\n");
                    Socket socket = new Socket(InetAddress.getByName(tf_Ip.getText()),Integer.parseInt(tf_port.getText()));
                    handler.GetSocket(socket);
                    handler.GetUserName(UserName);
                    messageArea.append("Client connected…\n");
                    handler.SendMessage("加入聊天");
                    new Thread(new MessageGet(socket, messageArea)).start();
                } catch (Exception er) {
                    er.printStackTrace();
                }
            }
        });

        sayButton.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e)
            {
                handler.SendMessage(sayTextField.getText());
                sayTextField.setText("");        //输入框置空
            }
        });

        MainFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

    }

    //方法:setShow
    //设置窗口可见
    public void setShow()
    {
        MainFrame.setVisible(true);
    }
}

//客户端发言部分的处理
class Handler {
    private Socket socket;
    private String UserName;

    public void GetSocket(Socket socket)
    {
        this.socket = socket;
    }
    public void GetUserName(String UserName)
    {
        this.UserName = UserName;
    }

    //方法:SendMessage
    //处理按钮按下后的处理
    public void SendMessage(String message)
    {
        try {
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            bufferedWriter.write(UserName + ":" + message+"\n");
            bufferedWriter.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

//类:MessageGet
//实现Runable接口,实时监控输入
class MessageGet implements Runnable{
    private Socket socket;
    private TextArea messageArea;

    public MessageGet(Socket socket,TextArea messageArea)
    {
        this.socket = socket;
        this.messageArea = messageArea;
    }

    @Override
    public void run()
    {
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while(true)
            {
                String message = bufferedReader.readLine();
                messageArea.append(message+"\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

  • 2
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值