Java实现UDP网络通信的程序设计实例

Java实现UDP网络通信的程序设计实例

学到java网络通信这一章,简单记录一下两种常见的通信协议:

  1. TCP通信协议,类似两个人打电话,提供两台计算机之间的数据互传,传播的数据准确可靠;
  2. UDP通信协议,是一种无连接的通信协议,类似发广播,不保障数据能可靠传输,适用于数据准确性要求不高,但对传输速度和时效性要求比较高的网站。

服务器端程序

package Number;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Sender extends Thread {
    
    
    Date date = new Date();
    SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
    String weather = "节目预报:今晚八点有大型晚会,注意收听收看";
    InetAddress inetAddress;
    int port = 9898;
    MulticastSocket socket;

    public Sender() {
    
    
        try {
    
    
            inetAddress = InetAddress.getByName("224.255.10.0");
            socket = new MulticastSocket(port);
            socket.joinGroup(inetAddress);
        } catch (UnknownHostException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
    
    
        super.run();
        while (true) {
    
    
            DatagramPacket packet;
            String message = "[" + format.format(date) + "]" + weather;
            byte[] data = message.getBytes();
            packet = new DatagramPacket(data, data.length, inetAddress, port);
            System.out.println(message);
            try {
    
    
                socket.send(packet);
                Thread.sleep(1000);
            } catch (IOException e) {
    
    
                e.printStackTrace();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
    
    
        Sender send = new Sender();
        send.start();
    }
}

客户端接收广播程序

import com.sun.javafx.logging.JFRInputEvent;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.*;

public class Receive extends JFrame implements Runnable, ActionListener {
    
    
    JButton ince = new JButton("开始接收");
    JButton stop = new JButton("停止接收");
    JTextArea inceAr = new JTextArea(10, 10);
    JTextArea inced = new JTextArea(10, 10);

    Thread thread;
    boolean getMessage = true;

    InetAddress inetAddress;
    int port = 9898;
    MulticastSocket socket;


    public Receive() {
    
    
        super("广播数据报");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        inceAr.setForeground(Color.blue);

        JPanel north = new JPanel();
        north.add(ince);
        north.add(stop);
        ince.addActionListener(this);
        stop.addActionListener(this);

        add(north, BorderLayout.NORTH);

        JPanel center = new JPanel();
        center.setLayout(new GridLayout(1, 2));
        center.add(inceAr);
        final JScrollPane js = new JScrollPane();
        center.add(js);
        js.setViewportView(inced);
//        center.add(inced);
        add(center, BorderLayout.CENTER);
        thread = new Thread(this);
        validate();
        setBounds(100, 50, 800, 380);

        try {
    
    
            inetAddress = InetAddress.getByName("224.255.10.0");
            socket = new MulticastSocket(port);
            socket.joinGroup(inetAddress);
        } catch (UnknownHostException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
    
    
        while (getMessage) {
    
    
            DatagramPacket packet;
            byte[] data = new byte[1024];
            packet = new DatagramPacket(data, data.length, inetAddress, port);
            try {
    
    
                socket.receive(packet);
                String message = new String(packet.getData(), 0, packet.getLength());
                inceAr.setText("正在接收的广播:\n" + message);
                inced.append(message + "\n");
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }

    }

    public void actionPerformed(ActionEvent e) {
    
    
        if (e.getSource() == ince) {
    
    
            ince.setBackground(Color.red);
            stop.setBackground(Color.yellow);
            if (!thread.isAlive()) {
    
    
                thread = new Thread(this);
                getMessage = true;
            }
            thread.start();
        }
        if (e.getSource() == stop) {
    
    
            ince.setBackground(Color.yellow);
            stop.setBackground(Color.red);
            getMessage = false;
        }

    }

    public static void main(String[] args) {
    
    
        Receive receive = new Receive();
//        receive.setSize(460, 200);
        receive.setVisible(true);
    }
}

先记录swing中几个容易忘记的知识点:

  1.         center.add(inceAr);
            final JScrollPane js = new JScrollPane();
            center.add(js);
            js.setViewportView(inced);
    //        center.add(inced);
            add(center, BorderLayout.CENTER);
    

    这里是swing的基础,就是滚动条到底该怎么设置,inced是一个文本域,它接收的信息很多,可能会超出文本域的范围,所以有必要加入一个滚动条,首先是新建了一个滚动条final JScrollPane js = new JScrollPane();至于为要强调是常量,我还没搞明白,待以后再去深挖。在布局中先添加这个滚动条,js.setViewportView(inced);这行代码挺重要,意思是滚动条中设置视口,并在括号内设置视图为inced,也可以使用下面的代码:

    final JScrollPane js = new JScrollPane(inced);
    

    即创建滚动条的时候,就把文本域inced添加到其中,之前有一篇博客提到过,但还是忘了,所以这是一个很容易忘记的知识点。

  2. public class Receive extends JFrame implements Runnable, ActionListener在创建类的时候,这个类就继承自JFrame类,然后实现了Runnable和ActionListener这两个接口,Runnable要实现的话,需要重写run方法;以往在swing中,给按钮设置监听方法时,都是在实例化按钮时直接给按钮重写监听方法(如下面的代码),采用实现接口的方式来写监听还没接触过,因此要记录一下,说明有这种写法。

        private JButton getCloseButton(){
          
          
            closeButton = new JButton("读取文件");
            closeButton.addActionListener(new ActionListener() {
          
          
                @Override
                public void actionPerformed(ActionEvent e) {
          
          
                    File file = new File("text.txt");
                    try {
          
          
                        FileReader reader = new FileReader(file);
                        char chars[] = new char[1024];
                        int len = reader.read(chars);
                        jTextArea.setText(new String(chars, 0, len));
                        reader.close();
    
                    } catch (FileNotFoundException fileNotFoundException) {
          
          
                        fileNotFoundException.printStackTrace();
                    } catch (IOException ioException) {
          
          
                        ioException.printStackTrace();
                    }
                }
            });
            return closeButton;
    // 这段代码也是本人其他博客中的内容,这中写法类似于重写了创建按钮方法,返回的是一个按钮对象,这个按钮对象中直接添加了监听方法
    // 这也是实现监听的一种方法
    
  3. 如何判断哪个按钮被点击了呢,if (e.getSource() == ince)就是这行代码,通过e.getSource()方法来判断被点击的按钮,来写不同按钮点击后应实现的功能,这有个好处,就是不用像上面一样,每次创建一个按钮,就来给这个按钮添加一个监听方法,这也是要重点学习的方法。

UDP网络通信的理解

  1. 首先,要搞清楚DatagramPacket类,这个类用来表示数据包,看看它的参数:
DatagramPacket(data, data.length, inetAddress, port);
  • 第一个参数data是需要传输的数据
  • 第二个单数是传输数据的长度
  • 第三个参数是地址
  • 第四个参数是端口

类似于寄快递,要寄的东西,东西有多重,收件人地址和收件人

  1. 然后,要搞明白套接字socket,它实例化的地方在构造方法这里:

    socket = new MulticastSocket(port);
    

    MulticastSocket可以将数据报以广播的方式发送到多个客户端,也就是说,这句代码实现了多点广播套接字。只需要指定端口,然后用joinGroup方法将广播组加入即可。

  2. 接收类中,用到了一个receive方法来接收数据包。

示例结果

先启动服务端程序Sender发送数据:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PC0taRti-1638175034292)(C:\Users\HP\Desktop\在办工作2021\99-其他临时工作\个人技术博客\image-20211129163222986.png)]

然后启动客户端程序:

QQ录屏20211129163338

猜你喜欢

转载自blog.csdn.net/u012848304/article/details/121613526