一、回传协议接口和UDP方式实现:
1.接口:
1
2
3
4
5
6
7
8
|
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.实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
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客户端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
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服务端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
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(); } } } } |
以上就是本文的全部内容,查看更多Java的语法,也希望大家多多支持服务器之家。