zoukankan      html  css  js  c++  java
  • UDP/IP+BIO/NIO/多播

    轉自:https://www.xuebuyuan.com/3215260.html

    UDP是无连接的,尽最多努力的,面向报文的网络传输层协议。

    Java对UDP/IP方式的网络数据通信采用的仍然是Socket机制。UDP的Socket是无连接的,要进行双向的通信,需要两端都成为UDP服务器端。

    Java中使用DatagramSocket和DatagramPocket来实现UDP+BIO模式的网络交互。

    DatagramSocket负责监听端口及读写数据流。DatagramPacket作为数据流对象进行传输。

    通常实现代码如下:

           DatagramSocketserverSocket=new DatagramSocket(PORT);
           byte[] buffer=new byte[65535];
           DatagramPacket receivePacket=new DatagramPacket(buffer,buffer.length);
          
           byte[] datas=new byte[]{0,1,0,1};
           InetAddress server=Inet4Address.getLocalHost();
           DatagramSocket socket=new DatagramSocket();
           DatagramPacket packet=new DatagramPacket(datas,datas.length,server,PORT);
           //阻塞发送packet到指定的服务器和端口,当网络IO出现异常时抛出IOException,
           //当连接不上目标地址和端口抛出PortUnreachableException
           socket.send(packet);
          
           //阻塞并同步读读取流信息,如接收到的流信息比packet长度长,则删除更长的信息,
           //可以通过setSoTimeout()方法设置读取流的超时时间。
           serverSocket.receive(receivePacket);

    以上是一个UDP端得实现代码,客户端和服务器端实现均类似。

    对于客户端,UDP无需建立连接,因此没有TCP/IP通信连接竞争的问题。但存在,最终流读写问题,读写数据流是同步的,阻塞的。

    对于服务器端,同时接受多个请求,可以对发送过来的一个DatagramPacket放到一个线程中进行处理。

    UDP+NIO

    类似的,在java中可以通过DatagramChannle和ByteBuffer类来实现UDP+NIO方式的通信。

    DatagramChannel可以负责监听端口和进行读/写操作。ByteBuffer用于数据传输。基于这两个类实现主要代码如下:

         

     //接收流数据
           DatagramChannelreceiveChannel=DatagramChannel.open();
           receiveChannel.configureBlocking(false);
           DatagramSocketsocket=receiveChannel.socket();
           socket.bind(new InetSocketAddress(LOCAL_HOST,receivePort));
           Selector selector=Selector.open();
           receiveChannel.register(selector,SelectionKey.OP_READ);
           //类似TCP+NIO方式对selector中的SelectionKey进行遍历,读取流信息
          
           //发送流数据
           DatagramChannelsendChannel=DatagramChannel.open();
           sendChannel.configureBlocking(false);
           SocketAddress addr=new InetSocketAddress(LOCAL_HOST,sendPort);
           sendChannel.connect(addr);
    //阻塞写入数据,如发送缓存区已满,返回0,此时可通过注册SelectionKey.OP_WRITE
           //事件,以便在可写入时,在进行写操作.代码略。
           sendChannel.write(byteBufferData);

    NIO中,只有在有数据Buffer读取或可写入buffer数据时才做相应的IO操作,而不用阻塞当前线程。

    前面的TCP+BIO,TCP+NIO,UDP+BIO,UDP+NIO,谈到的都是一对一的网络通信。在实际情况中,经常存在要将消息发送到多台机器。对于这种情况,

    第一种方案,显然很容易想到,使用多个连接建立,发送多个数据信息,这时发送方显然可能面临较大的发送压力,尤其是传输视频数据的时候。

    在计算机网络课程中,有IP多播内容。在一对多的通信中,多播只需要发送一份多播数据报,并且只发送一次即可,可大大节省网络资源。《计算机网络》, 谢希仁P164。

    在java中,可基于MulticastSocket和DatagramPacket实现多播网络通信。MulticastSocket继承于DatagramSocket,它能基于UDP/IP实现多播方式的网络通信。在多播通信中,不同的地方在于接收数据端通过加入多播组来进行数据的接收,同样发送数据端也要求加入到多播组进行发送。多播组使用D类IP地址,其范围为:224.0.0.0~239.2555.255.255。每一个D类地址标志一个多播组。基于多播实现网络通信代码如下:

     

    InetAddress groupAddress=InetAddress.getByName("224.0.0.1");
           MulticastSocket server=new MulticastSocket(port);
           //加入多播组,如果地址为非多播地址,抛出IOException,当不希望在发送
           //或读取数据到多播地址时,可通过调用server.leaveGroup(多播地址),离开多播
           server.joinGroup(groupAddress);
          
           //发送Socket
           MulticastSocket sendSocket=new MulticastSocket();
           sendSocket.joinGroup(groupAddress);
          
    //然后,可通过UDP+BIO方式,使用receive和send进行读/写操作

    在java应用中,多播多用于多台机器之间状态的同步。使用多播的java项目:JGroup.

  • 相关阅读:
    MongoDB的特殊操作
    MongoDB的$作为下标的用法
    MongoDB之$关键字,以及$修饰器$set,$inc,$push,$pull,$pop
    MongoDB的数据类型
    MongoDB的增删改查
    Drozer快速使用指南
    [安全分析报告]使用某科技公司客服系统的风险分析
    某客服系统上传漏洞导致服务器被拿下(续)
    YS端对端之间SSL通信安全问题
    某客服系统上传漏洞导致服务器被拿下
  • 原文地址:https://www.cnblogs.com/sharpest/p/12702763.html
Copyright © 2011-2022 走看看