📜  在Java中使用 UDP 数据报套接字

📅  最后修改于: 2022-05-13 01:54:51.097000             🧑  作者: Mango

在Java中使用 UDP 数据报套接字

DatagramSockets 是 Java 通过 UDP 而不是 TCP 进行网络通信的机制。 Java提供 DatagramSocket 来通过 UDP 而不是 TCP 进行通信。它也建立在 IP 之上。 DatagramSockets 可用于通过 Internet 发送和接收数据包。

UDP 优于 TCP 的示例之一是电视频道的实时报道。在这方面,我们希望向现场观众传输尽可能多的帧,而不用担心丢失一两帧。 TCP 作为一种可靠的协议,在传输时会增加自己的开销。
另一个首选 UDP 的例子是在线多人游戏。在反恐精英或使命召唤等游戏中,不需要传递所有信息,而是传递最重要的信息。还应该注意的是,现实生活中的大多数应用程序都使用了 UDP 和 TCP 的仔细混合;通过 TCP 传输关键数据,通过 UDP 传输其余数据。

本文是单面客户端-服务器程序的简单实现,其中客户端向服务器发送消息,服务器只打印它,直到客户端发送“再见”。

Java数据报编程模型步骤

  1. DatagramSocket 的创建:首先,创建一个 datagramSocket 对象以将数据包传送到目的地,并在服务器发送任何数据时接收它。要创建 datagramSocket,可以使用以下构造函数:
    • 受保护的 DatagramSocket DatagramSocket():
      Syntax: public DatagramSocket()
                    throws SocketException
      Creates a datagramSocket and binds it to any available
      port on local machine. If this constructor is used, the
      OS would assign any port to this socket.
      
    • 受保护的 DatagramSocket DatagramSocket(int port):-
      Syntax: public DatagramSocket(int port)
                              throws SocketException
      Parameters:
      port - port to which socket is to be bound
      Throws:
      SocketException - If the socket cannot be bound to the 
      specific local port. Creates a DatagramSocket and binds 
      to the specified port on the local machine.
    • protected DatagramSocket DatagramSocket(int port, InetAddress inetaddress):-
      Syntax: public DatagramSocket(int port,
                             InetAddress inetaddress)
                              throws SocketException
      Parameters:
      port - port to which socket is to be bound.
      inetaddress - local address to which socket is to be bound.
      Throws:
      SocketException - If the socket cannot be bound to the 
      specific local port. It creates a DatagramSocket and 
      binds it to specified port and ip-address.
      
  2. 创建DatagramPacket:在此步骤中,创建用于通过datagramSocket 发送/接收数据的数据包。
    • 发送数据的构造函数: DatagramPacket(byte buf[], int length, InetAddress inetaddress, int port):-
      Syntax: public DatagramPacket(byte[] buf,
                    int offset,
                    int length,
                    SocketAddress address)
      Parameters:
      buf - the packet data.
      offset - the packet data offset.
      length - the packet data length.
      address - the destination socket address.
      Constructs a DatagramPacket for sending data at specified address
       and specified port.
    • 接收数据的构造函数:
      DatagramPacket(byte buf[], int length):-
      Syntax: public DatagramPacket(byte buf[],
                    int length)
      Parameters:
      buf - the packet data.
      length - the packet data length.
      Constructs a DatagramPacket for receiving the data of length length
      in the byte array buf.
      
  3. 在套接字对象上调用 send() 或 receive() 调用
    Syntax: void send(DatagramPacket packet)
                               throws SocketException
    Parameters:
    packet - Datagrampacket to send.
    Throws:
    SocketException - If there is an error in binding.
    IllegalArgumentException - if address is not supported by the socket.
    
    Syntax: void receive(DatagramPacket packet)
                               throws SocketException
    Parameters:
    packet - Datagrampacket to receive from this socket.
    Throws:
    SocketException - If there is an error in binding.
    IllegalArgumentException - if address is not supported by the socket.
    

客户端实现

Java
// Java program to illustrate Client side
// Implementation using DatagramSocket
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
  
public class udpBaseClient_2
{
    public static void main(String args[]) throws IOException
    {
        Scanner sc = new Scanner(System.in);
  
        // Step 1:Create the socket object for
        // carrying the data.
        DatagramSocket ds = new DatagramSocket();
  
        InetAddress ip = InetAddress.getLocalHost();
        byte buf[] = null;
  
        // loop while user not enters "bye"
        while (true)
        {
            String inp = sc.nextLine();
  
            // convert the String input into the byte array.
            buf = inp.getBytes();
  
            // Step 2 : Create the datagramPacket for sending
            // the data.
            DatagramPacket DpSend =
                  new DatagramPacket(buf, buf.length, ip, 1234);
  
            // Step 3 : invoke the send call to actually send
            // the data.
            ds.send(DpSend);
  
            // break the loop if user enters "bye"
            if (inp.equals("bye"))
                break;
        }
    }
}


Java
// Java program to illustrate Server side
// Implementation using DatagramSocket
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
  
public class udpBaseServer_2
{
    public static void main(String[] args) throws IOException
    {
        // Step 1 : Create a socket to listen at port 1234
        DatagramSocket ds = new DatagramSocket(1234);
        byte[] receive = new byte[65535];
  
        DatagramPacket DpReceive = null;
        while (true)
        {
  
            // Step 2 : create a DatgramPacket to receive the data.
            DpReceive = new DatagramPacket(receive, receive.length);
  
            // Step 3 : revieve the data in byte buffer.
            ds.receive(DpReceive);
  
            System.out.println("Client:-" + data(receive));
  
            // Exit the server if the client sends "bye"
            if (data(receive).toString().equals("bye"))
            {
                System.out.println("Client sent bye.....EXITING");
                break;
            }
  
            // Clear the buffer after every message.
            receive = new byte[65535];
        }
    }
  
    // A utility method to convert the byte array
    // data into a string representation.
    public static StringBuilder data(byte[] a)
    {
        if (a == null)
            return null;
        StringBuilder ret = new StringBuilder();
        int i = 0;
        while (a[i] != 0)
        {
            ret.append((char) a[i]);
            i++;
        }
        return ret;
    }
}


输出:

Hello
I am Client.
...
bye

服务器端实现

Java

// Java program to illustrate Server side
// Implementation using DatagramSocket
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
  
public class udpBaseServer_2
{
    public static void main(String[] args) throws IOException
    {
        // Step 1 : Create a socket to listen at port 1234
        DatagramSocket ds = new DatagramSocket(1234);
        byte[] receive = new byte[65535];
  
        DatagramPacket DpReceive = null;
        while (true)
        {
  
            // Step 2 : create a DatgramPacket to receive the data.
            DpReceive = new DatagramPacket(receive, receive.length);
  
            // Step 3 : revieve the data in byte buffer.
            ds.receive(DpReceive);
  
            System.out.println("Client:-" + data(receive));
  
            // Exit the server if the client sends "bye"
            if (data(receive).toString().equals("bye"))
            {
                System.out.println("Client sent bye.....EXITING");
                break;
            }
  
            // Clear the buffer after every message.
            receive = new byte[65535];
        }
    }
  
    // A utility method to convert the byte array
    // data into a string representation.
    public static StringBuilder data(byte[] a)
    {
        if (a == null)
            return null;
        StringBuilder ret = new StringBuilder();
        int i = 0;
        while (a[i] != 0)
        {
            ret.append((char) a[i]);
            i++;
        }
        return ret;
    }
}

简而言之,我们可以总结通过 UDP 发送和接收数据的步骤如下:-

  1. 对于通过 UDP 发送数据包,我们应该知道 4 件事,要发送的消息、消息长度、目标 IP 地址、目标正在侦听的端口。
  2. 一旦我们知道了所有这些事情,我们就可以创建用于承载数据包和实际拥有数据的数据包的套接字对象。
  3. 调用 send()/receive() 调用以实际发送/接收数据包。
  4. 从接收到的数据包中提取数据。

输出:

Client:- Hello
Client:- I am client.
...
Client:- bye
Client sent bye.....EXITING

注意:- 为了在系统上测试上述程序,请确保您先运行服务器程序,然后再运行客户端程序。确保您在客户端控制台中,并从那里继续输入您的消息,每条消息后跟一个回车符。每次发送消息时,您都会被重定向到服务器控制台,具体取决于您的环境设置。如果没有自动重定向,请切换到服务器控制台以确保收到所有消息。最后要终止通信,输入“bye”(不带引号)并回车。

作为一个热心的读者,您还应该尝试实现一个双向聊天应用程序,其中服务器将能够在他喜欢的时候响应消息。

参考:
http://下载。 Java.net/jdk7/archive/b123/docs/api/ Java/net/DatagramSocket.html
http://下载。 Java.net/jdk7/archive/b123/docs/api/ Java/net/DatagramPacket.html