Java的NIO包中,有一個專門用于發送UDP資料包的類:DatagramChannel,UDP是一種無連接配接的網絡協定,
一般用于發送一些準确度要求不太高的資料等。
完整的服務端程式如下:
public class StatisticsServer {
//每次發送接收的資料包大小
private final int MAX_BUFF_SIZE = * ;
//服務端監聽端口,用戶端也通過該端口發送資料
private int port;
private DatagramChannel channel;
private Selector selector;
private ScheduledExecutorService es = Executors.newScheduledThreadPool();
public void init() throws IOException {
//建立通道和選擇器
selector = Selector.open();
channel = DatagramChannel.open();
//設定為非阻塞模式
channel.configureBlocking(false);
channel.socket().bind(new InetSocketAddress(port));
//将通道注冊至selector,監聽隻讀消息(此時服務端隻能讀資料,無法寫資料)
channel.register(selector, SelectionKey.OP_READ);
//使用線程的方式,保證服務端持續等待接收用戶端資料
es.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
while(selector.select() > ) {
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while(iterator.hasNext()) {
SelectionKey key = iterator.next();
try {
iterator.remove();
if(key.isReadable()) {
//接收資料
doReceive(key);
}
} catch (Exception e) {
logger.error("SelectionKey receive exception", e);
try {
if (key != null) {
key.cancel();
key.channel().close();
}
} catch (ClosedChannelException cex) {
logger.error("Close channel exception", cex);
}
}
}
}
} catch (IOException e) {
logger.error("selector.select exception", e);
}
}
}, L, L, TimeUnit.MINUTES);
}
//處理接收到的資料
private void doReceive(SelectionKey key) throws IOException {
String content = "";
DatagramChannel sc = (DatagramChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(MAX_BUFF_SIZE);
buffer.clear();
sc.receive(buffer);
buffer.flip();
while(buffer.hasRemaining()) {
byte[] buf = new byte[buffer.limit()];
buffer.get(buf);
content += new String(buf);
}
buffer.clear();
logger.debug("receive content="+content);
if(StringUtils.isNotBlank(content)) {
doSave(content);
}
}
}
用戶端發送完整例子如下:
DatagramChannel channel = DatagramChannel.open();
StringBuilder sb = new StringBuilder();
sb.append("2017-03-09 12:30:00;")
.append("aaa")
.append("testapp;")
.append("test.do;")
.append("param=hello;")
.append("test;")
.append("100;")
.append("1");
ByteBuffer buffer = ByteBuffer.allocate();
buffer.clear();
buffer.put(sb.toString().getBytes());
buffer.flip();
//此處IP為服務端IP位址,端口和服務端的端口一緻
int n = channel.send(buffer, new InetSocketAddress("127.0.0.1", ));
System.out.println(n);
//每次資料發送完畢之後,一定要調用close方法,來關閉占用的udp端口,否則程式不結束,端口不會釋放
channel.close();