一、回传协议接口和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的语法,也希望大家多多支持服务器之家。