UDP的Nio实现
net 包下
DatagramSocket
/DatagramPacket
实现的udp我倒是蛮熟悉,一直没去学习nio里面提供的udp
实现。我一直觉得udp不存在连接,根本没必要使用selector
轮询。但是Java确实提供了这样的实现。今天经过一番学习,才弄明白。原来它的意义是可以通过一个Selector(一个线程)
来轮询多个udp的服务。
Server
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
public class NioUdpServer {
public static void main(String[] args) throws Exception {
Selector selector = Selector.open();
DatagramChannel datagramChannel = DatagramChannel.open();
try{
datagramChannel.bind(new InetSocketAddress(1024));
// 非阻塞模式
datagramChannel.configureBlocking(false);
// 一些socket的选项
datagramChannel.setOption(StandardSocketOptions.SO_REUSEADDR, Boolean.TRUE);
// 只关心读事件
datagramChannel.register(selector, SelectionKey.OP_READ);
// 预定义缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(65507);
while (selector.select() > 0){
Iterator<SelectionKey> selectionKeyIterator = selector.selectedKeys().iterator();
while (selectionKeyIterator.hasNext()){// 读事件
SelectionKey selectionKey = selectionKeyIterator.next();
try{
if(selectionKey.isReadable()){
DatagramChannel channel = (DatagramChannel) selectionKey.channel();
// 客户端地址信息
InetSocketAddress inetSocketAddress = (InetSocketAddress) channel.receive(byteBuffer);
String hostName = inetSocketAddress.getHostName();
int port = inetSocketAddress.getPort();
String hostString = inetSocketAddress.getHostString();
System.out.println(hostName + "[" + hostString +"]:" + port);
// 数据信息
byteBuffer.flip();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
byteBuffer.clear();
System.out.println(new String(bytes, StandardCharsets.UTF_8));
}else if(selectionKey.isWritable()){
}else if(selectionKey.isAcceptable()){
}else if(selectionKey.isConnectable()){
}else{ }
}finally {
selectionKeyIterator.remove();
}
}
}
}finally {
selector.close();
datagramChannel.close();
}
}
}
Client
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.charset.StandardCharsets;
public class NioClient {
public static void main(String[] args) throws Exception{
DatagramChannel datagramChannel = DatagramChannel.open();
datagramChannel.setOption(StandardSocketOptions.SO_REUSEADDR, Boolean.TRUE);
// 绑定发送端口
datagramChannel.bind(new InetSocketAddress(7725));
ByteBuffer byteBuffer = ByteBuffer.allocate(65507);
byteBuffer.put("SpringBoot中文社区".getBytes(StandardCharsets.UTF_8));
byteBuffer.flip();
// 返回已经成功发送的字节数量, 可能一次性没发送完毕
int count = datagramChannel.send(byteBuffer, new InetSocketAddress("127.0.0.1", 1024));
System.out.println(count);
}
}