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(); } } } }
以上就是本文的全部內(nèi)容,查看更多Java的語法,大家可以關(guān)注:《Thinking in Java 中文手冊(cè)》、《JDK 1.7 參考手冊(cè)官方英文版》、《JDK 1.6 API java 中文參考手冊(cè)》、《JDK 1.5 API java 中文參考手冊(cè)》,也希望大家多多支持腳本之家。
相關(guān)文章
mybatis插件實(shí)現(xiàn)自定義改寫表名實(shí)例代碼
在數(shù)據(jù)庫操作過程中,經(jīng)常有修改表名的需求,下面這篇文章主要給大家介紹了關(guān)于mybatis插件實(shí)現(xiàn)自定義改寫表名的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04Spring中的@CrossOrigin注解的使用詳細(xì)解讀
這篇文章主要介紹了Spring中的@CrossOrigin注解的使用詳細(xì)解讀,跨源資源共享(CORS),是由大多數(shù)瀏覽器實(shí)現(xiàn)的W3C規(guī)范,允許對(duì)跨域請(qǐng)求進(jìn)行靈活授權(quán),用來代替IFRAME或JSONP等非正規(guī)實(shí)現(xiàn)方式,需要的朋友可以參考下2023-11-11Java正則表達(dá)式學(xué)習(xí)之分組與替換
這篇文章主要給大家介紹了關(guān)于Java正則表達(dá)式學(xué)習(xí)之分組與替換的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09深入理解Java虛擬機(jī) JVM 內(nèi)存結(jié)構(gòu)
本節(jié)將會(huì)介紹一下JVM的內(nèi)存結(jié)構(gòu),JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)的各個(gè)組成部分:堆,方法區(qū),程序計(jì)數(shù)器,Java虛擬機(jī)棧,本地方法棧,還會(huì)對(duì)Java堆的分代劃分做個(gè)簡單的介紹2021-09-09JAVA中重寫(Override)與重載(Overload)的相關(guān)示例
這篇文章主要給大家介紹了關(guān)于JAVA中重寫(Override)與重載(Overload)的相關(guān)示例,重寫(override)和重載(overload)是兩種不同的方法重用技術(shù),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10基于Java實(shí)現(xiàn)PDF文本旋轉(zhuǎn)傾斜
這篇文章主要介紹了基于Java實(shí)現(xiàn)PDF文本旋轉(zhuǎn)傾斜,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05并發(fā)編程之Java內(nèi)存模型volatile的內(nèi)存語義
這篇文章主要介紹了并發(fā)編程之Java內(nèi)存模型volatile的內(nèi)存語義,理解volatile特性的一個(gè)好辦法是把對(duì)volatile變量的單個(gè)讀/寫,看成是使用同一個(gè)鎖對(duì)單個(gè)讀/寫操作做了同步。下面我們一起進(jìn)入文章看看具體例子吧,需要的小伙伴可以參考下2021-11-11舉例講解Java的Spring框架中AOP程序設(shè)計(jì)方式的使用
這篇文章主要介紹了Java的Spring框架中AOP程序設(shè)計(jì)方式的使用講解,文中舉的AOP下拋出異常的例子非常實(shí)用,需要的朋友可以參考下2016-04-04