Java Socket編程實(shí)例(五)- NIO UDP實(shí)踐
一、回傳協(xié)議接口和UDP方式實(shí)現(xiàn):
1.接口:
import java.nio.channels.SelectionKey;
import java.io.IOException;
public interface EchoProtocol {
void handleAccept(SelectionKey key) throws IOException;
void handleRead(SelectionKey key) throws IOException;
void handleWrite(SelectionKey key) throws IOException;
}
2.實(shí)現(xiàn):
import java.net.SocketAddress;
import java.nio.channels.*;
import java.nio.ByteBuffer;
import java.io.IOException;
public class UDPEchoSelectorProtocol implements <span style="font-size: 1em; line-height: 1.5;">EchoProtocol </span><span style="font-size: 1em; line-height: 1.5;">{</span>
private static final int ECHOMAX = 255; // Maximum size of echo datagram
static class ClientRecord {
public SocketAddress clientAddress;
public ByteBuffer buffer = ByteBuffer.allocate(ECHOMAX);
}
public void handleAccept(SelectionKey key) throws IOException {
}
public void handleRead(SelectionKey key) throws IOException {
DatagramChannel channel = (DatagramChannel) key.channel();
ClientRecord clntRec = (ClientRecord) key.attachment();
clntRec.buffer.clear(); // Prepare buffer for receiving
clntRec.clientAddress = channel.receive(clntRec.buffer);
if (clntRec.clientAddress != null) { // Did we receive something?
// Register write with the selector
key.interestOps(SelectionKey.OP_WRITE);
}
}
public void handleWrite(SelectionKey key) throws IOException {
DatagramChannel channel = (DatagramChannel) key.channel();
ClientRecord clntRec = (ClientRecord) key.attachment();
clntRec.buffer.flip(); // Prepare buffer for sending
int bytesSent = channel.send(clntRec.buffer, clntRec.clientAddress);
if (bytesSent != 0) { // Buffer completely written?
// No longer interested in writes
key.interestOps(SelectionKey.OP_READ);
}
}
}
二、NIO UDP客戶端:
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
public class UDPEchoClientNonblocking {
private static final int TIMEOUT = 3000; // Resend timeout (milliseconds)
private static final int MAXTRIES = 255; // Maximum retransmissions
public static void main(String args[]) throws Exception {
// Convert input String to bytes using the default charset
byte[] bytesToSend = "0123456789abcdefghijklmnopqrstuvwxyz".getBytes();
// Create channel and set to nonblocking
DatagramChannel datagramChannel = DatagramChannel.open();
datagramChannel.configureBlocking(false);
datagramChannel.socket().setSoTimeout(TIMEOUT);
ByteBuffer writeBuf = ByteBuffer.wrap(bytesToSend);
ByteBuffer readBuf = ByteBuffer.allocate(MAXTRIES);
datagramChannel = datagramChannel.connect(new InetSocketAddress("127.0.0.1", 5500));
int totalBytesRcvd = 0; // Total bytes received so far
int bytesRcvd; // Bytes received in last read
while (totalBytesRcvd < bytesToSend.length) {
if (writeBuf.hasRemaining()) {
datagramChannel.write(writeBuf);
}
if ((bytesRcvd = datagramChannel.read(readBuf)) == -1) {
throw new SocketException("Connection closed prematurely");
}
totalBytesRcvd += bytesRcvd;
System.out.print("."); // Do something else
}
System.out.println("Received: " + new String(readBuf.array(), 0, totalBytesRcvd));
datagramChannel.close();
}
}
三、NIO UDP服務(wù)端:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.*;
import java.util.Iterator;
public class UDPEchoServerSelector {
private static final int TIMEOUT = 3000; // Wait timeout (milliseconds)
public static void main(String[] args) throws IOException {
// Create a selector to multiplex client connections.
Selector selector = Selector.open();
DatagramChannel channel = DatagramChannel.open();
channel.configureBlocking(false);
channel.socket().bind(new InetSocketAddress(5500));
channel.register(selector, SelectionKey.OP_READ, new UDPEchoSelectorProtocol.ClientRecord());
UDPEchoSelectorProtocol echoSelectorProtocol = new UDPEchoSelectorProtocol();
while (true) { // Run forever, receiving and echoing datagrams
// Wait for task or until timeout expires
if (selector.select(TIMEOUT) == 0) {
System.out.print(".");
continue;
}
// Get iterator on set of keys with I/O to process
Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();
while (keyIter.hasNext()) {
SelectionKey key = keyIter.next(); // Key is bit mask
// Client socket channel has pending data?
if (key.isReadable())
echoSelectorProtocol.handleRead(key);
// Client socket channel is available for writing and
// key is valid (i.e., channel not closed).
if (key.isValid() && key.isWritable())
echoSelectorProtocol.handleWrite(key);
keyIter.remove();
}
}
}
}
以上就是本文的全部?jī)?nèi)容,查看更多Java的語(yǔ)法,大家可以關(guān)注:《Thinking in Java 中文手冊(cè)》、《JDK 1.7 參考手冊(cè)官方英文版》、《JDK 1.6 API java 中文參考手冊(cè)》、《JDK 1.5 API java 中文參考手冊(cè)》,也希望大家多多支持腳本之家。
相關(guān)文章
SpringMVC如何把后臺(tái)文件打印到前臺(tái)
這篇文章主要介紹了SpringMVC如何把后臺(tái)文件打印到前臺(tái),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
java實(shí)現(xiàn)百度云OCR文字識(shí)別 高精度OCR識(shí)別身份證信息
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)百度云OCR文字識(shí)別,高精度OCR識(shí)別身份證信息,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
Spring Boot Swagger2使用方法過(guò)程解析
這篇文章主要介紹了Spring Boot Swagger2使用方法過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
探索jedis連接池預(yù)熱優(yōu)化高并發(fā)
這篇文章主要為大家介紹了jedis連接池預(yù)熱優(yōu)化高并發(fā)深入探索示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
詳解Mybatis多參數(shù)傳遞入?yún)⑺姆N處理方式
這篇文章主要介紹了詳解Mybatis多參數(shù)傳遞入?yún)⑺姆N處理方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
java 基于maven多模塊合并打包部署的操作過(guò)程
這篇文章主要介紹了java 基于maven多模塊合并打包部署的操作過(guò)程,本文通過(guò)實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02

