Java中的UDP通信

1 UDP通信机制

Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。与TCP协议不同,UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。在发送数据前,需要进行封包操作(使用 DatagramPacket 类),才能发送和接收数据(使用 DatagramSocket 类)。

使用UDP传输数据时,可能存在的问题有:

丢失包;

乱序;

错误包;

数据包的重复发送。

通常需要使用UDP的场景主要是对数据流要求不高时,如视频流、音频流等。

2 UDP 通信编程的一般步骤

  • 创建客户端的 DatagramSocket 并定义客户端用来接收报文的端口;

  • 创建服务器端的 DatagramSocket 并定义服务端用来接收报文的端口;

  • 在服务器端创建 DatagramPacket 对象,封装待发送的数据包;

  • 客户端发送报文;

  • 服务器端接收报文。

3 服务端

服务端接收数据使用 DatagramSocket对象,创建对象时,需要指定一个用于接收请求的端口。

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpServer {
    public static void main(String[] args) {
        try {
            //创建服务端接收数据的 DatagramSocket 对象
            DatagramSocket datagramSocket = new DatagramSocket(5555);
            //创建数据缓冲区
            byte[] buff = new byte[1024];
            //创建数据报的包对象
            DatagramPacket packet = new DatagramPacket(buff, buff.length);
            //等待接收客户端发送的数据
            datagramSocket.receive(packet);
            //获取数据
            String input = new String(packet.getData(), 0, packet.getLength());

            System.out.println("接收到客户端的请求: " + input);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在接收客户端发来的请求时,使用了字节缓冲区,可以一次性接收 1024 个字节的数据,可以减少网络IO的操作。

在服务端和客户端之间的数据流使用 DatagramPacket 封装,因此在接收数据时,应使用该对象进行接收。

datagramSocket.receive(packet);方法是一个阻塞式方法,当没有接收到数据时,程序将在这里等待,接收到数据后,才会继续执行下边的代码。

在接收到字节数据后,如果不想直接使用二进制数据,需要对数据进行转换。

在获取接收到的数据时,使用的是 new String(packet.getData(), 0, packet.getLength()) ,并没有读取缓冲区的所有内容,因为当从网卡中读取的实际数据,若长度小于缓冲区长度时,其数据对于服务端来说是没有意义的。我们仅需要拿走实际接收到的数据报即可。

4 客户端

创建客户端时,也需要创建一个 DatagramSocket 对象,同时指定发送数据的端口,如果和服务端在同一台机器上时,该端口应与服务端不同。

在客户端发送数据时,需要将数据封装到 DatagramPacket 对象中,同时需要指定接收数据的服务端IP及端口。

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.util.Scanner;

public class UdpClient {
    public static void main(String[] args) {
        try {
            //创建数据发送对象,并指定要发送数据的端口
            DatagramSocket socket = new DatagramSocket(5556);
            //将要发送的数据转换为字节数组
            Scanner scanner = new Scanner(System.in);
            String output = scanner.next();
            byte[] bytes = output.getBytes();
            //创建数据报的包对象
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length, new InetSocketAddress("127.0.0.1", 5555));
            //发送消息
            socket.send(packet);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5 通信

5.1 不启动服务端

当没有启动服务端,只启动客户端发送数据时,客户端将数据正常发出而没有报错。

image.png

可见客户端在发送数据时,并没有对服务端进行检查。

5.2 启动服务端

image.png

这是一次通信,如果想要建立多次通信,可以在服务端加上循环,方法同 TCP 通信类似。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
UDP(User Datagram Protocol)是一种无连接协议,它不像TCP(Transmission Control Protocol)一样建立连接和维护状态,而是将数据报直接发送给目标主机,不保证数据的可靠性和有序性,但是可以提高数据传输的效率和速度。在Java,可以使用Java API提供的DatagramSocket和DatagramPacket类实现UDP通讯。 下面是一个简单的Java UDP通讯的例子: ```java import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPServer { public static void main(String[] args) throws Exception { DatagramSocket serverSocket = new DatagramSocket(9876); byte[] receiveData = new byte[1024]; byte[] sendData = new byte[1024]; while (true) { DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); serverSocket.receive(receivePacket); String sentence = new String(receivePacket.getData()); InetAddress IPAddress = receivePacket.getAddress(); int port = receivePacket.getPort(); String capitalizedSentence = sentence.toUpperCase(); sendData = capitalizedSentence.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); serverSocket.send(sendPacket); } } } ``` ```java import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPClient { public static void main(String[] args) throws Exception { DatagramSocket clientSocket = new DatagramSocket(); InetAddress IPAddress = InetAddress.getByName("localhost"); byte[] sendData = new byte[1024]; byte[] receiveData = new byte[1024]; String sentence = "Hello, server!"; sendData = sentence.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876); clientSocket.send(sendPacket); DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); clientSocket.receive(receivePacket); String modifiedSentence = new String(receivePacket.getData()); System.out.println("FROM SERVER:" + modifiedSentence); clientSocket.close(); } } ``` 在这个例子UDPServer类和UDPClient类分别表示UDP服务器和UDP客户端。服务器端使用DatagramSocket类绑定到本地9876端口,并且使用一个循环来接收来自客户端的数据报,将接收到的数据报转换为大写形式,并将其发送回客户端。客户端使用DatagramSocket类创建一个UDP套接字,并将消息“Hello, server!”转换为字节数组,然后将其作为DatagramPacket发送到服务器。客户端然后等待接收从服务器返回的响应,并将其转换为字符串形式打印出来。 需要注意的是,由于UDP是无连接的协议,因此无法保证数据报的到达顺序和可靠性,需要根据具体情况考虑如何处理可能出现的数据包丢失或乱序的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我有健康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值