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

由于不想学GUI、所以很大程度上是面向GPT完成的实验。

**************程序仅供参考**************

实验题目及其要求

1.掌握Java中GUI程序的编写,包括事件监听机制。

    2.掌握Java的网络通信编程,ServerSocket,Socket类的使用。

    3.掌握Java中多线程的编程,Thread类,Runnable接口的使用。

    4.掌握用面向对象的方法分析和解决复杂问题。

实验内容

编写程序完成以下功能:

  1. 设计一个基于GUI的客户-服务器的通信应用程序,如图1、图2所示。

图1 Socket通信服务器端界面

图2 Socket通信客户端界面

2.图1为Socket通信服务器端界面,点击该界面中的【Start】按钮,启动服务器监听服务(在图1界面中间的多行文本区域显示“Server starting…”字样)。图2为Socket通信客户端界面,点击该界面中的【Connect】按钮与服务器建立链接,并在图2所示界面中间的多行文本区域显示“Connect to server…”字样,当服务器端监听到客户端的连接后,在图1界面中间的多行文本区域追加一行“Client connected…”字样,并与客户端建立Socket连接。

3.当图1所示的服务器端和图2所示的客户机端建立Socket连接后,编程实现服务端、客户端之间的“单向通信”:在客户端的输入界面发送消息,在服务端接收该消息,并将接收到对方的数据追加显示在多行文本框中。

思考题

1. 对整个实验进行总结,写出实验心得。

2. 在完成上述实验内容的基础上,尝试实现“双向通信”功能,即服务端、客户端之间可以相互发送、接收消息,并以此作为实验成绩评优的加分依据

--------------------------------------------------------------------------------------------------------

实验代码及部分解析

先放上实验结果。根据实验要求,实现了双向通信,并且允许多个客户端进行连接(此处服务端的通信逻辑是“广播”形式,这一点可以拓展成“指定某客户端进行通信”的形式)。

客户端与服务端的代码基本一致,这里只说下服务端的代码。

在服务端中,主要的代码内容有3块儿,分别是UI的编写发送消息的逻辑监听进程的编写

监听进程我是使用“Runnable接口实现”的方式做的,这一点可以换成“Thread子类”来实现,并且每当监听到一个用户的socket连接请求时,会将该用户的信息加入到一个“List”中。

private List<PrintWriter> clientWriters = new ArrayList<>();//用于存放所有连接的客户端

服务端发送消息时会根据上面的“List”,将消息广播给所有客户端。

代码的文件格式如下:

其中ClientGUI_Test与ClientGUI一模一样(注意修改public class的类名等),这里是为了更好地展现“1Server、2Client” 。

下面是具体的代码实现:

ServerGUI.java

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class ServerGUI extends JFrame {
    private JTextArea textArea;//消息显示区域
    private JTextField portTextField;//端口输入框
    private JTextField messageTextField;
    private List<PrintWriter> clientWriters = new ArrayList<>();//用于存放所有连接的客户端
    private Thread serverThread;//服务端的监听进程

    public ServerGUI() {
        setTitle("Socket通信服务器端");
        setSize(560, 350);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //服务器设置区域,首先创建一个面板用于包装"服务器设置"部分
        JPanel serverSettingsPanel = new JPanel(new BorderLayout());
        serverSettingsPanel.setBorder(BorderFactory.createTitledBorder("服务端设置区:")); // 添加标题

        portTextField = new JTextField(5);
        portTextField.setText("8888");
        serverSettingsPanel.add(new JLabel("Port: "), BorderLayout.WEST);
        serverSettingsPanel.add(portTextField, BorderLayout.CENTER);

        JButton startButton = new JButton("Start");
        startButton.addActionListener(e -> startServer());
        serverSettingsPanel.add(startButton, BorderLayout.EAST);

        // 添加"服务器设置"面板到主界面
        add(serverSettingsPanel, BorderLayout.NORTH);

        //消息显示区域
        JPanel messageShowPanel = new JPanel(new BorderLayout());
        messageShowPanel.setBorder(BorderFactory.createTitledBorder("消息接收区:"));
        textArea = new JTextArea();
        textArea.setEditable(false);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        JScrollPane scrollPane = new JScrollPane(textArea);
        messageShowPanel.add(scrollPane, BorderLayout.CENTER);
        add(messageShowPanel, BorderLayout.CENTER);

        //消息编辑区域
        JPanel messageEditPanel = new JPanel(new BorderLayout());
        messageEditPanel.setBorder(BorderFactory.createTitledBorder("消息编辑区:"));
        messageTextField = new JTextField(20);
        JButton sendButton = new JButton("Say");
        sendButton.addActionListener(e -> sendMessageToClients());
        messageEditPanel.add(new JLabel("Say: "), BorderLayout.WEST);
        messageEditPanel.add(messageTextField);
        messageEditPanel.add(sendButton, BorderLayout.EAST);
        add(messageEditPanel, BorderLayout.SOUTH);
    }

    private void startServer() {
        try {
            int port = Integer.parseInt(portTextField.getText());
            ServerSocket serverSocket = new ServerSocket(port);
            appendText("Server starting on port " + port + "...");
            serverThread = new Thread(() -> {
                try {
                    while (true) {
                        Socket clientSocket = serverSocket.accept();
                        String IP_and_Port = clientSocket.getInetAddress().getHostAddress() + ": " + clientSocket.getPort();
                        appendText("Client(" + IP_and_Port + ") connected...");
                        clientWriters.add(new PrintWriter(clientSocket.getOutputStream(), true));

                        //启动监听进程
                        ClientReceiver handler = new ClientReceiver(clientSocket, IP_and_Port);
                        new Thread(handler).start();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            serverThread.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void sendMessageToClients() {
        String message = messageTextField.getText();

        //广播形式发送消息
        for (PrintWriter writer : clientWriters) {
            if(writer != null){
                writer.println(message);
            }
        }

        messageTextField.setText("");
    }

    private void appendText(String message) {
        SwingUtilities.invokeLater(() -> {
            textArea.append(message + "\n");
            System.out.println(message);
        });
    }

    private class ClientReceiver implements Runnable {
        private Socket clientSocket;
        private String clientInfo;
        private BufferedReader reader;

        public ClientReceiver(Socket socket, String clientInfo) {
            this.clientSocket = socket;
            this.clientInfo = clientInfo;
            try {
                reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            try {
                String message;
                while ((message = reader.readLine()) != null) {
                    appendText("Client(" + clientInfo + "): " + message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            ServerGUI server = new ServerGUI();
            server.setVisible(true);
        });
    }
}

ClientGUI.java

import javax.swing.*;
import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ClientGUI extends JFrame {
    private JTextArea textArea;
    private JTextField ipAddressTextField;
    private JTextField portTextField;
    private JTextField messageTextField;
    private Socket socket;
    private PrintWriter out;

    public ClientGUI() {


        setTitle("Socket通信客户端");
        setSize(560, 350);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //客户端设置区域
        JPanel clientSettingsPanel = new JPanel();
        clientSettingsPanel.setBorder(BorderFactory.createTitledBorder("客户端设置区:"));
        ipAddressTextField = new JTextField(15);
        ipAddressTextField.setText("localhost");
        clientSettingsPanel.add(new JLabel("IP Address:"), BorderLayout.WEST);
        clientSettingsPanel.add(ipAddressTextField);

        portTextField = new JTextField(5);
        portTextField.setText("8888");
        clientSettingsPanel.add(new JLabel("Port:"));
        clientSettingsPanel.add(portTextField);

        JButton connectButton = new JButton("Connect");
        connectButton.addActionListener(e -> connectToServer());
        clientSettingsPanel.add(connectButton, BorderLayout.EAST);

        // 添加"服务器设置"面板到主界面
        add(clientSettingsPanel, BorderLayout.NORTH);

        //消息显示区域
        //消息显示区域
        JPanel messageShowPanel = new JPanel(new BorderLayout());
        messageShowPanel.setBorder(BorderFactory.createTitledBorder("消息接收区:"));
        textArea = new JTextArea();
        textArea.setEditable(false);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        JScrollPane scrollPane = new JScrollPane(textArea);
        messageShowPanel.add(scrollPane, BorderLayout.CENTER);
        add(messageShowPanel, BorderLayout.CENTER);

        //消息编辑区域
        JPanel messageEditPanel = new JPanel(new BorderLayout());
        messageEditPanel.setBorder(BorderFactory.createTitledBorder("消息编辑区:"));
        messageTextField = new JTextField(20);
        JButton sendButton = new JButton("Say");
        sendButton.addActionListener(e -> sendMessageToServer());
        messageEditPanel.add(new JLabel("Say: "), BorderLayout.WEST);
        messageEditPanel.add(messageTextField);
        messageEditPanel.add(sendButton, BorderLayout.EAST);
        add(messageEditPanel, BorderLayout.SOUTH);
    }

    private void connectToServer() {
        String ipAddress = ipAddressTextField.getText();
        int port = Integer.parseInt(portTextField.getText());

        try {
            socket = new Socket(ipAddress, port);
            out = new PrintWriter(socket.getOutputStream(), true);
            String IP_and_Port = socket.getLocalAddress() + ": " + socket.getLocalPort();
            appendText("Connected to server at " + ipAddress + ":" + port + "  Current: " + IP_and_Port);

            //启动监听线程
            ServerReceiver handle = new ServerReceiver(socket);
            new Thread(handle).start();
        } catch (Exception e) {
            e.printStackTrace();
            appendText("Connection failed.");
        }
    }

    private void sendMessageToServer() {
        String message = messageTextField.getText();

        if (out != null) {
            out.println(message);
        }

        messageTextField.setText("");
    }

    private void appendText(String message) {
        SwingUtilities.invokeLater(() -> {
            textArea.append(message + "\n");
            System.out.println(message);
        });
    }

    private class ServerReceiver implements Runnable {
        private BufferedReader reader;

        public ServerReceiver(Socket socket) {
            try {
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            try {
                String message;
                while ((message = reader.readLine()) != null) {
                    appendText("Server: " + message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            ClientGUI client = new ClientGUI();
            client.setVisible(true);
        });
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值