轉自:https://www.xuebuyuan.com/3215260.html
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.