Vert.x 核心模块 UDP数据报访问(十四)

    xiaoxiao2022-06-23  17

    数据报SOCKET(UDP)

    用Vert.x中的用户数据报文协议是很好的。UDP是无连接传输这基本意味着你不必保存远程端点的连接。相反可以接收或发送数据包,而远程地址包含在数据包中。除了UDP使用没有TCP一样安全,这就是说,采用UDP发送数据不保证发出的数据报文一定会被收到。仅有的保证是要么完整收到要么没收到。也就是说不能发送超过网卡MTU大小的数据,这是因为每个数据报将被作为一个包发送。必须注意甚至小于MTU的包也有可能失败。什么大小的包会失败取决于操作系统等因素,所以首要准则是发送小报文。由于UDP具有的特性,它很适合发送允许丢包的应用(如应用监控的例子)。好处是它与TCP比较,省了很多开销,UDP可用NetServer和NetClient进行处理。

    创建一个DatagramSocket

    为了使用UDP,首先需要创建DatagramSocket。然后就可以发送数据和接收数据了

    DatagramSocket socket =vertx.createDatagramSocket(new DatagramSocketOptions());

    DatagramSocket不必绑定了特定端口。这样象客户端一样发送数据没有问题,更多的内容在下一节讨论.

     发送数据包

    如前所述,UDP用包来发送数据到远端,但是不需以长连接的方式。这就意示着不同的包可以发送到不同的远程端点。发送包可以象下面显示的一样简单:

    DatagramSocket socket =vertx.createDatagramSocket(new DatagramSocketOptions());

    Buffer buffer =Buffer.buffer("content");

    // Send a Buffer

    socket.send(buffer, 1234, "10.0.0.1",asyncResult -> {

     System.out.println("Send succeeded? " +asyncResult.succeeded());

    });

    // Send a String

    socket.send("A string used ascontent", 1234, "10.0.0.1", asyncResult -> {

     System.out.println("Send succeeded? " +asyncResult.succeeded());

    });

     接收数据报

    为了接收数据包,通过listen(…)方法绑定到DatagramSocket。这样将从绑定的地址和端口接数据包了(DatagramPacket)。除此,也需要为DatagramSocket设置一个在接收到数据时调用的处理器。

    DatagramPacket有以下方法:

    ·          sender:是一个代表发送数据包的地址(InetSocketAddress)

    ·          data:承载接收数据的缓冲器(Buffer)

    为了在指定的地址和端口侦听,可以象下面显示这样做:

    DatagramSocket socket = vertx.createDatagramSocket(newDatagramSocketOptions());

    socket.listen(1234, "0.0.0.0",asyncResult -> {

      if(asyncResult.succeeded()) {

       socket.handler(packet -> {

          //Do something with the packet

        });

      } else{

       System.out.println("Listen failed" + asyncResult.cause());

      }

    });

    甚至代码 AsyncResult标识是成功的,这仅表示可以在网络堆栈上被写入,而不能保证数据一定到达或将会到达远程端点。如是需要可靠的传输,可以在传送数据之前使用TCP握手逻辑。

     多播

    发送多播包

    多播是允许多个Socket接收同样的数据包。通过将socket加入到多播组,然后向多播组发送数据。让我们看一下怎样加入多播组,接收数据将在下一节讨论。现在让我们关注怎样发送数据。发送多播包与发送正常的数据报包没有什么不同,只是在向send方法传递的是多播组参数。如下所示:

    DatagramSocket socket =vertx.createDatagramSocket(new DatagramSocketOptions());

    Buffer buffer =Buffer.buffer("content");

    // Send a Buffer to a multicast address

    socket.send(buffer, 1234,"230.0.0.1", asyncResult -> {

     System.out.println("Send succeeded? " +asyncResult.succeeded());

    });

    所有Socket都加入多播组230.0.0.1,并将接收数据。

     接收多播包

    如果需要要接收数据包,只需要用listen(…)方法将DatagramSocket绑定的特定的多播组并加入多播组。这样将会从接收到来自DatagramSocket侦听的地址和端口发送来的DatagramPacket,同时也可以发送DatagramPacket到多播组。也可以在接到DatagraPacket时调用设置的处理器。

    DatagramPacket有以下方法:

    ·          sender():代表包发送者的地址(InetSocketAddress)

    ·          data():承载接收数据的缓冲器(Buffer)

    侦听指定的端口和地址,并且从多播组230.0.0.1上接收数据,可以象下面这样做:

    DatagramSocket socket =vertx.createDatagramSocket(new DatagramSocketOptions());

    socket.listen(1234, "0.0.0.0",asyncResult -> {

      if(asyncResult.succeeded()) {

       socket.handler(packet -> {

          //Do something with the packet

        });

        //join the multicast group

       socket.listenMulticastGroup("230.0.0.1", asyncResult2 -> {

           System.out.println("Listen succeeded? " + asyncResult2.succeeded());

        });

      } else{

       System.out.println("Listen failed" + asyncResult.cause());

      }

    });

     解除侦听/离开多播组

    有一些情况下需要在限定的时间内从多播组中接收数据。在此情 况下,首先得开始侦听,稍后解侦听。下面是代码:

    DatagramSocket socket =vertx.createDatagramSocket(new DatagramSocketOptions());

    socket.listen(1234, "0.0.0.0",asyncResult -> {

        if(asyncResult.succeeded()) {

         socket.handler(packet -> {

           // Do something with the packet

          });

           //join the multicast group

         socket.listenMulticastGroup("230.0.0.1", asyncResult2 -> {

             if (asyncResult2.succeeded()) {

               // will now receive packets for group

                // do some work

                socket.unlistenMulticastGroup("230.0.0.1", asyncResult3 ->{

                 System.out.println("Unlisten succeeded? " +asyncResult3.succeeded());

               });

             } else {

               System.out.println("Listen failed" + asyncResult2.cause());

             }

          });

        }else {

         System.out.println("Listen failed" + asyncResult.cause());

        }

    });

     阻塞式多播

    除了解除一个多播地址外,阻塞特定的发送地址也是可行的。要小心这仅可以工作在某些操作系统和内核版本。因此请检查操作系统文档确定其是否支持,这是一个高手特性。多指定的地址阻塞多播,可以在DatagramSocket调用blockMulticastGroup(..)方法,如下所示:

    DatagramSocket socket =vertx.createDatagramSocket(new DatagramSocketOptions());

     // Some code

     // This would block packets which are send from10.0.0.2

    socket.blockMulticastGroup("230.0.0.1","10.0.0.2", asyncResult -> {

     System.out.println("block succeeded? " +asyncResult.succeeded());

    });

     DagatramSocket属性

    在创建一个DatagramSocket时,通过DatagramSocketOption对象设置多个属性可以改变DatagramSocket的行为。这此属性如下:

    ·          setSendBufferSize设置发送缓冲器字节大小。

    ·          setReceiveBufferSize设置TCP接收缓冲器字节大小。

    ·          setResueAddress如果为true,在socket被关闭后,TIME_WAIT状态下的地址可重用。

    ·          setTrafficClass

    ·          setBroadcast设置或清除SO_BROADCAST socket选项。设置此选项时,UDP包可以被发送到本地网卡的广播地址。

    ·          setMulticastNetworkInterface设置或清除IP_MULTICAST_LOOP socket选项。设置此选项,多播包可以在本地网卡上被接收。

    ·          setMulticastTimeToLive设置IP_MULTICAST_TTL socket选项。TTL代表“Timeto Live,”,但是在此上下文,TTL指的是包允许通过网络的跳数,特别是在多播传输时。每一个路由器或网关在传输包时会减省TTL。如果TTL被路由器减少到0时,包将不会被路由。

     DatagramSocket本地地址

    通过调用localAddress方法,你可以发现Socket的本地地址(如UDP Socket这侧的地址)。如果你用listen(…)进行DatagramSocket进行绑定,你将得到一个InetSocketAddress实例,如果在调用listen(…)之前调用localAddress方法,你会得到null值。

     关闭DatagramSocket

    可以调用close方法关闭socket,这将关闭socket并释放资源。
    转载请注明原文地址: https://ju.6miu.com/read-1123319.html

    最新回复(0)