java NIO实现UDP通讯
NIO Udp通讯工具类
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import lombok.extern.slf4j.Slf4j;
/**
* NIO Udp工具类
*/
@Slf4j
public class MyUdpSocket {
//获取报文的通道
private DatagramChannel channel;
//多路复用选择器
private Selector selector;
private final int MAX_SIZE = 1280;
//当前获取到版本的端口
private int client_port;
//记录当前获取到报文的ip
private String client_ip;
ByteBuffer receive_buffer = ByteBuffer.allocate(MAX_SIZE);
public MyUdpSocket(String ip, int port) throws IOException {
channel=DatagramChannel.open();
selector=Selector.open();
try{
//调整此通道为非阻塞模式
channel.configureBlocking(false);
//获取与套接字通道关联的套接字,并将该套接字绑定到本机指定端口
channel.socket().bind(new InetSocketAddress(port));
//为通道选择器注册通道,并指定操作的选择键集
channel.register(selector, SelectionKey.OP_READ);
}catch (IOException e) {
log.error("MyUdpSocket init error", e);
}
}
/**
* 接收数据
* @return
*/
public final int receive() {
try{
receive_buffer.clear();
if(selector.select(1000)!=0) {
Iterator<SelectionKey> itr = selector.selectedKeys().iterator();
while(itr.hasNext()){
SelectionKey key = itr.next( );
itr.remove();
if(key.isReadable()){
DatagramChannel dc = (DatagramChannel)key.channel();
InetSocketAddress client = (InetSocketAddress)dc.receive(receive_buffer); //接收来自任意一个Client的数据报
if (client!=null) {
client_ip=client.getAddress().getHostAddress();
client_port=client.getPort();
//System.out.println(client_ip+":"+client_port+" size="+receive_buffer.position());
key.interestOps(SelectionKey.OP_READ);
return receive_buffer.position();
} else {
return 0;
}
} else {
return 0;
}
}
}
}catch (IOException e) {
log.error(String.format("udp_receive出错:%s", e.getMessage()), e);
}
return 0;
}
public final void close() throws IOException {
selector.close();
channel.close();
}
public final int get_client_port(){
return client_port;
}
public final String get_client_ip(){
return client_ip;
}
public final byte[] get_receive_packet(int size){
byte[] packet = new byte[size];
for (int i=0; i<size; i++){
packet[i]=receive_buffer.array()[i];
}
return packet;
}
public final void get_receive_buffer(byte[] buffer){
receive_buffer.get(buffer);
}
}
用法:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class UdpSocketTest {
public static void main(String[] args) throws IOException {
MyUdpSocket socket = new MyUdpSocket("127.0.0.1", 1234);
while(true) {
int size = socket.receive();
if (size>0) {
byte[] data = socket.get_receive_packet(size);
System.out.println("ip:" + socket.get_client_ip());
DatagramPacket packet = new DatagramPacket(data, 0, data.length);
packet.setSocketAddress(new InetSocketAddress(socket.get_client_ip(), socket.get_client_port()));
DatagramSocket datagramSocket = new DatagramSocket(null);
datagramSocket.setReuseAddress(true);
datagramSocket.send(packet);
datagramSocket.close();
}
}
}
}