Java Socket編程實例(五)- NIO UDP實踐
一、回傳協(xié)議接口和UDP方式實現(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.實現(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 中文手冊》、《JDK 1.7 參考手冊官方英文版》、《JDK 1.6 API java 中文參考手冊》、《JDK 1.5 API java 中文參考手冊》,也希望大家多多支持腳本之家。
相關(guān)文章
深入理解Java虛擬機 JVM 內(nèi)存結(jié)構(gòu)
本節(jié)將會介紹一下JVM的內(nèi)存結(jié)構(gòu),JVM運行時數(shù)據(jù)區(qū)的各個組成部分:堆,方法區(qū),程序計數(shù)器,Java虛擬機棧,本地方法棧,還會對Java堆的分代劃分做個簡單的介紹2021-09-09JAVA中重寫(Override)與重載(Overload)的相關(guān)示例
這篇文章主要給大家介紹了關(guān)于JAVA中重寫(Override)與重載(Overload)的相關(guān)示例,重寫(override)和重載(overload)是兩種不同的方法重用技術(shù),文中通過代碼介紹的非常詳細,需要的朋友可以參考下2023-10-10基于Java實現(xiàn)PDF文本旋轉(zhuǎn)傾斜
這篇文章主要介紹了基于Java實現(xiàn)PDF文本旋轉(zhuǎn)傾斜,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-05-05并發(fā)編程之Java內(nèi)存模型volatile的內(nèi)存語義
這篇文章主要介紹了并發(fā)編程之Java內(nèi)存模型volatile的內(nèi)存語義,理解volatile特性的一個好辦法是把對volatile變量的單個讀/寫,看成是使用同一個鎖對單個讀/寫操作做了同步。下面我們一起進入文章看看具體例子吧,需要的小伙伴可以參考下2021-11-11舉例講解Java的Spring框架中AOP程序設(shè)計方式的使用
這篇文章主要介紹了Java的Spring框架中AOP程序設(shè)計方式的使用講解,文中舉的AOP下拋出異常的例子非常實用,需要的朋友可以參考下2016-04-04