当前位置:   article > 正文

Java UDP 客户端服务器程序示例_java 创建一个udp服务

java 创建一个udp服务

在本 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发送和接收DatagramPacketDatagramSocket表示网络中两台计算机之间的 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 ():关闭套接字。

这些方法可以抛出IOExceptionPortUnreachableExceptionSocketTimeoutException ……所以你必须捕捉或重新抛出它们。有关 完整的详细信息,请参阅 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参考:

 

相关 Java 网络教程:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/146702
推荐阅读
相关标签
  

闽ICP备14008679号