在本 Java 网络编程教程中,您将学习如何编写基于 UDP 协议的客户端/服务器应用程序。

首先,让我们看看 Java Network API 是如何设计来支持使用 UDP 的网络应用程序开发的。

DatagramPacket DatagramSocket是用于实现 UDP 客户端/服务器应用程序的两个主要类。DatagramPacket是一个数据容器,DatagramSocket是一种发送和接收DatagramPacket的机制。

1. 数据报包

在 UDP 的术语中,传输的数据被封装在一个称为数据报的单元中。数据报是通过网络发送的一个独立的、自包含的消息,其到达、到达时间和内容都没有保证。而在 Java 中,DatagramPacket代表一个数据报。

您可以使用以下构造函数之一创建DatagramPacket对象:

  • DatagramPacket(byte[] buf, int length)
  • DatagramPacket(byte[] buf, int 长度, InetAddress 地址, int 端口)

如您所见,数据必须采用字节数组的形式。第一个构造函数用于创建要接收的DatagramPacket。

第二个构造函数创建了一个要发送的DatagramPacket,所以需要指定目的主机的地址和端口号。

参数 length 指定要使用的字节数组中的数据量,通常是数组的长度(buf.length)。


 

还有其他构造函数允许您指定字节数组中的偏移量,以及使用SocketAddress:

  • DatagramPacket(byte[] buf, int offset, int length)
  • DatagramPacket(byte[] buf, int offset, int length, SocketAddress 地址)

此外,DatagramPacket为地址、数据和端口号提供了 setter 和 getter 方法。有关完整的详细信息,请参阅其DatagramPacket Javadoc。

2. 数据报套接字

您使用DatagramSocket发送和接收DatagramPacket。DatagramSocket表示网络中两台计算机之间的 UDP 连接。

在 Java 中,我们对客户端和服务器都使用DatagramSocket。客户端和服务器没有单独的类,如 TCP 套接字。

因此,您可以使用以下构造函数之一创建一个DatagramSocket对象来建立用于发送和接收数据报的 UDP 连接:

  • 数据报套接字()
  • DatagramSocket(int 端口)
  • DatagramSocket(int 端口,InetAddress 梯形图)

无参数构造函数用于创建绑定到任意端口号的客户端。第二个构造函数用于创建绑定到特定端口号的服务器,以便客户端知道如何连接。

第三个构造函数将服务器绑定到指定的 IP 地址(以防计算机有多个 IP 地址)。

如果无法打开套接字,或者套接字无法绑定到指定的端口或地址,则这些构造函数可以抛出SocketException。所以你已经捕获或重新抛出这个已检查的异常。

DatagramSocket的关键方法包括:

  • send (DatagramPacket p):发送数据报包。
  • 接收(DatagramPacket p):接收数据报包。
  • setSoTimeout (int timeout):以毫秒为单位设置超时时间,限制接收数据时的等待时间。如果超时到期,则会引发SocketTimeoutException。
  • close ():关闭套接字。

这些方法可以抛出IOException、PortUnreachableException、SocketTimeoutException ……所以你必须捕捉或重新抛出它们。有关 完整的详细信息,请参阅 DatagramSocket Javadoc。

现在,让我们看看一些运行中的示例程序。

3. Java UDP 客户端示例

我们将为一个客户端程序编写代码,该程序从实现每日报价 (QOTD) 服务(一种 Internet 标准)的服务器请求报价。以下代码片段将DatagramPacket发送到由主机名和端口指定的服务器:

1
2
3
4
5
6
7
8
9
10
String hostname = "djxmmx.net";
int port = 17;
 
InetAddress address = InetAddress.getByName(hostname);
DatagramSocket socket = new DatagramSocket();
 
byte[] buffer = new byte[512];
 
DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, port);
socket.send(request);

如您所见,缓冲区没有数据,因为 QOTD 服务不需要客户端发送任何特定消息。并且您必须在DatagramPacket 中指定服务器的地址和端口。所以这段代码只是向服务器发送一个信号,暗示“嘿,我想从你那里得到一个报价”。

下面的代码片段从服务器接收一个DatagramPacket:

1
2
3
4
5
6
DatagramPacket response = new DatagramPacket(buffer, buffer.length);
socket.receive(response);
 
String quote = new String(buffer, 0, response.getLength());
 
System.out.println(quote);

如您所见,一旦套接字打开,接收数据包非常简单。并且代码将字节数组转换为以可读格式打印的字符串。

这是完整客户端程序的代码,它参数化主机名和端口号,处理异常并每 10 秒从服务器获取报价:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import java.io.*;
import java.net.*;
 
/**
 * This program demonstrates how to implement a UDP client program.
 *
 *
 * @author www.codejava.net
 */
public class QuoteClient {
 
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Syntax: QuoteClient <hostname> <port>");
            return;
        }
 
        String hostname = args[0];
        int port = Integer.parseInt(args[1]);
 
        try {
            InetAddress address = InetAddress.getByName(hostname);
            DatagramSocket socket = new DatagramSocket();
 
            while (true) {
 
                DatagramPacket request = new DatagramPacket(new byte[1], 1, address, port);
                socket.send(request);
 
                byte[] buffer = new byte[512];
                DatagramPacket response = new DatagramPacket(buffer, buffer.length);
                socket.receive(response);
 
                String quote = new String(buffer, 0, response.getLength());
 
                System.out.println(quote);
                System.out.println();
 
                Thread.sleep(10000);
            }
 
        catch (SocketTimeoutException ex) {
            System.out.println("Timeout error: " + ex.getMessage());
            ex.printStackTrace();
        catch (IOException ex) {
            System.out.println("Client error: " + ex.getMessage());
            ex.printStackTrace();
        catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

要测试此客户端程序,请键入以下命令:

1
java QuoteClient djxmmx.net 17

djxmmx.net是我们可以使用的公共QOTD服务器,17是为QOTD服务预留的端口号。

你会看到这样的输出:

1
2
3
4
5
6
7
"When a stupid man is doing something he is ashamed of, he always declares that it is his duty." George Bernard Shaw (1856-1950)
 
"Oh the nerves, the nerves; the mysteries of this machine called man!
 Oh the little that unhinges it, poor creatures that we are!"
 Charles Dickens (1812-70)
 
 In Heaven an angel is nobody in particular." George Bernard Shaw (1856-1950)

如果您自己测试这个程序,您可能会看到不同的引号,因为服务器返回随机引号。按 Ctrl + C 终止程序。

4. Java UDP 服务器示例

下面的示例程序演示了如何为上述客户端实现服务器。以下代码创建一个 UDP 服务器,监听端口 17 并等待客户端的请求:

1
2
3
4
5
6
DatagramSocket socket = new DatagramSocket(17);
 
byte[] buffer = new byte[256];
 
DatagramPacket request = new DatagramPacket(buffer, buffer.length);
socket.receive(request);

的接收() ,直到接收到一个数据报的方法块。下面的代码向客户端发送一个DatagramPacket:

1
2
3
4
5
6
7
8
InetAddress clientAddress = request.getAddress();
int clientPort = request.getPort();
 
String data = "Message from server";
buffer = data.getBytes();
 
DatagramPacket response = new DatagramPacket(buffer, buffer.length, clientAddress, clientPort);
socket.send(response);

如您所见,服务器还需要知道客户端的地址和端口才能发送DatagramPacket。该信息可以从之前从客户端接收到的DatagramPacket 中获得。并且 String 被转换为一个字节数组,然后可以将其包装在DatagramPacket 中。

下面是一个功能齐全的服务器程序,它从文本文件中读取报价,并为每个客户端的请求发送一个随机报价。引用文件和端口号作为程序的参数给出。这是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import java.io.*;
import java.net.*;
import java.util.*;
 
/**
 * This program demonstrates how to implement a UDP server program.
 *
 *
 * @author www.codejava.net
 */
public class QuoteServer {
    private DatagramSocket socket;
    private List<String> listQuotes = new ArrayList<String>();
    private Random random;
 
    public QuoteServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
        random = new Random();
    }
 
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Syntax: QuoteServer <file> <port>");
            return;
        }
 
        String quoteFile = args[0];
        int port = Integer.parseInt(args[1]);
 
        try {
            QuoteServer server = new QuoteServer(port);
            server.loadQuotesFromFile(quoteFile);
            server.service();
        catch (SocketException ex) {
            System.out.println("Socket error: " + ex.getMessage());
        catch (IOException ex) {
            System.out.println("I/O error: " + ex.getMessage());
        }
    }
 
    private void service() throws IOException {
        while (true) {
            DatagramPacket request = new DatagramPacket(new byte[1], 1);
            socket.receive(request);
 
            String quote = getRandomQuote();
            byte[] buffer = quote.getBytes();
 
            InetAddress clientAddress = request.getAddress();
            int clientPort = request.getPort();
 
            DatagramPacket response = new DatagramPacket(buffer, buffer.length, clientAddress, clientPort);
            socket.send(response);
        }
    }
 
    private void loadQuotesFromFile(String quoteFile) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(quoteFile));
        String aQuote;
 
        while ((aQuote = reader.readLine()) != null) {
            listQuotes.add(aQuote);
        }
 
        reader.close();
    }
 
    private String getRandomQuote() {
        int randomIndex = random.nextInt(listQuotes.size());
        String randomQuote = listQuotes.get(randomIndex);
        return randomQuote;
    }
}

假设我们有一个Quotes.txt文件,其中包含以下内容(每个引号都在一行中):

1
2
3
4
5
Whether you think you can or you think you can't, you're right - Henry Ford
There are no traffic jams along the extra mile - Roger Staubach
Build your own dreams, or someone else will hire you to build theirs - Farrah Gray
What you do today can improve all your tomorrows - Ralph Marston
Remember that not getting what you want is sometimes a wonderful stroke of luck - Dalai Lama

键入以下命令以运行服务器程序:

1
java QuoteServer Quotes.txt 17

并运行客户端程序(在同一台计算机上):

1
java QuoteClient localhost 17

客户端和服务器都在无限循环中运行,因此您必须按 Ctrl + C 终止。

这就是关于如何开发依赖 UDP 协议的网络客户端/服务器应用程序的课程。基于这些知识,您可以开发通过 UDP 与服务器通信的客户端程序,并开发您自己的 UDP 客户端/服务器应用程序。

API参考:

  • 数据报包 Javadoc
  • 数据报套接字 Javadoc

相关 Java 网络教程:

  • Java InetAddress 示例
  • Java 套接字客户端示例 (TCP/IP)
  • Java 套接字服务器示例 (TCP/IP)

Java UDP 客户端服务器程序示例相关推荐

  1. java聊天程序步骤解析_java网络之基于UDP的聊天程序示例解析

    基于UDP的Socket通信 UDP协议不是一种基于稳定连接的协议,是一种面向数据报包的通信协议,不需要通信双方建立稳定的连接,也没有所谓服务端和客户的概念,数据报包在传输的时候不保证一定及时到达,也 ...

  2. udp文件服务器,UDP客户端服务器文件传输

    我想通过UDP将数据包从客户端发送到服务器.我面临的问题是,如果最后一个数据包大小小于我们正在读取的字节数组的大小,那么来自先前数据包的冗余数据将被附加到它.我试着只将最后一个数据包的正确部分复制到一 ...

  3. 【STM32F407】第11章 ThreadX NetXDUO之UDP客户端/服务器

    最新教程下载:ThreadX NetXDUO网络协议栈教程更新记录贴,前11章已经发布(2022-01-03) - uCOS & uCGUI & emWin & embOS & ...

  4. 【STM32H7】第11章 ThreadX NetXDUO之UDP客户端/服务器

    最新教程下载:ThreadX NetXDUO网络协议栈教程更新记录贴,前11章已经发布(2022-01-03) - uCOS & uCGUI & emWin & embOS & ...

  5. 客户端/服务器程序_了解客户端/服务器协议和Web应用程序

    客户端/服务器程序 Introduction 介绍 HyperText Transfer Protocol or "HTTP" is the underpinning of int ...

  6. java mongodb_MongoDB Java Servlet Web应用程序示例教程

    java mongodb Welcome to MongoDB Web Application example. Earlier in MongoDB Java Example we learned ...

  7. 基于UDP客户端服务器的编程模型-linux网络编程

    坚持在代码中注释,边读代码边学习Linux网络编程 使用到的发送函数原型: #include <sys/types.h>#include <sys/socket.h>ssize ...

  8. 【UNIX网络编程】| 【03】TCP客户/服务器程序示例

    文章目录 1.概述 2.TCP回射服务器程序 3.TCP回射客户程序 3.正常启动 4.正常终止 5.POSIX信号处理 5.1 signal函数 5.2 POSIX信号语义 6.处理SIGCHID信 ...

  9. java在客户端生成文件_用Java编写创建一对客户端/服务器程序,利用数据报将一个文件从一台主机传送到另一...

    展开全部 下面是e5a48de588b63231313335323631343130323136353331333337386564我自己写的一个读取并显示txt文件的demo,希望对您有帮助. pu ...

  10. java udp简单聊天程序_Java基于UDP协议实现简单的聊天室程序

    最近比较闲,一直在抽空回顾一些java方面的技术应用. 今天没什么事做,基于udp协议,写了一个非常简单的聊天室程序. 现在的工作,很少用到socket,也算是对java网络编程方面的一个简单回忆. ...

最新文章

  1. ROS关于cv_brige的使用
  2. SUMO输出车辆相关参数
  3. html模块化标签,jq load()方法实现html 模块化。
  4. java中实现同步的两种方式:syschronized和lock的区别和联系
  5. mysql事务用法介绍及储存引擎介绍(MyLSAM,Innodb)
  6. 8.3、Spring Profiles 功能及内部原理
  7. msfconsole启动失败并报错`not_after=‘: bignum too big to convert into `long‘的解决方法
  8. 持续集成(4)工具对比
  9. 如何发挥Intel傲腾持久内存最大能力?
  10. 华为手机一直android,华为手机内存不够用?这5个文件夹常清理,可以腾出近10个G内存...
  11. oracle视图在查询里,oracle视图
  12. QCOM chi-camera bring up
  13. 依概率收敛与按分布收敛
  14. ZenTao不支持Win8.1问题解决
  15. CS1703 C# Multiple assemblies with equivalent xxx... and. Remove one of the duplicate references.
  16. 怎么把两个PDF合并成一个?这几种操作轻松合并
  17. 详解Linux终端下编写“贪吃蛇”游戏
  18. tableau 连接python
  19. 基于深度学习的显著性目标检测方法综述
  20. 深入了解电容(二):电容的参数指标解释

热门文章

  1. matlab破解方法
  2. OTT TV 与 IPTV 的区别
  3. 如何解决Vosviewer关键词共现分析出现的Incorrect number of columns错误
  4. 用户故事与敏捷方法—一些用户故事(实战二)
  5. 【scratch高阶案例教学】scratch斐波那契数列 scratch创意编程 少儿编程 小朋友们也可以完成如此神奇的数列
  6. Telnet介绍及其安装
  7. Flex StringUtil工具类
  8. Keil(C51)的安装与注册
  9. 基于Java和Python实现简单的CA认证系统
  10. C语言/C++中strcpy_s函数