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

数据报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并释放资源。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值