1:selectionKey.channel()方法返回的 channel是ServerSocketChannel還是SocketChannel是由前邊注冊這個key時是注冊channel確定的。
2:基本處理流程
服務器端先注冊接收Key
serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT)
while(true){
selector.select();
Set<SelectionKey> keys=selector.selectedKeys();
Iterator it=keys.iterator();
while(it.hasNext()){
SelectionKey key=it.next();
it.remove();
處理key
}
3:一般ServerSocketChannel只注冊accept事件,對於read和write事件是注冊到accept的SocketChannel中的
public
class NIOServer {
/*標識數字*/
private
int flag
=
0;
/*緩沖區大小*/
private
int BLOCK
=
4096;
/*接受數據緩沖區*/
private ByteBuffer sendbuffer
= ByteBuffer.allocate(BLOCK);
/*發送數據緩沖區*/
private ByteBuffer receivebuffer
= ByteBuffer.allocate(BLOCK);
private Selector selector;
public NIOServer(
int port)
throws IOException {
// 打開服務器套接字通道
ServerSocketChannel serverSocketChannel
= ServerSocketChannel.open();
// 服務器配置為非阻塞
serverSocketChannel.configureBlocking(false);
// 檢索與此通道關聯的服務器套接字
ServerSocket serverSocket
= serverSocketChannel.socket();
// 進行服務的綁定
serverSocket.bind(
new InetSocketAddress(port));
// 通過open()方法找到Selector
selector
= Selector.open();
// 注冊到selector,等待連接
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println(
"Server Start----8888:");
}
// 監聽
private
void listen()
throws IOException {
while (true) {
// 選擇一組鍵,並且相應的通道已經打開
selector.select();
// 返回此選擇器的已選擇鍵集。
Set
<SelectionKey
> selectionKeys
= selector.selectedKeys();
Iterator
<SelectionKey
> iterator
= selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey
= iterator.next();
iterator.remove();
handleKey(selectionKey);
}
}
}
// 處理請求
private
void handleKey(SelectionKey selectionKey)
throws IOException {
// 接受請求
ServerSocketChannel server
= null;
SocketChannel client
= null;
String receiveText;
String sendText;
int count
=
0;
// 測試此鍵的通道是否已准備好接受新的套接字連接。
if (selectionKey.isAcceptable()) {
// 返回為之創建此鍵的通道。
server
= (ServerSocketChannel) selectionKey.channel();
// 接受到此通道套接字的連接。
// 此方法返回的套接字通道(如果有)將處於阻塞模式。
client
= server.accept();
// 配置為非阻塞
client.configureBlocking(false);
// 注冊到selector,等待連接
client.register(selector, SelectionKey.OP_READ);
}
else
if (selectionKey.isReadable()) {
// 返回為之創建此鍵的通道。
client
= (SocketChannel) selectionKey.channel();
//將緩沖區清空以備下次讀取
receivebuffer.clear();
//讀取服務器發送來的數據到緩沖區中
count
= client.read(receivebuffer);
if (count
>
0) {
receiveText
=
new String( receivebuffer.array(),
0,count);
System.out.println(
"服務器端接受客戶端數據--:"
+receiveText);
client.register(selector, SelectionKey.OP_WRITE);
}
}
else
if (selectionKey.isWritable()) {
//將緩沖區清空以備下次寫入
sendbuffer.clear();
// 返回為之創建此鍵的通道。
client
= (SocketChannel) selectionKey.channel();
sendText
=
"message from server--"
+ flag
++;
//向緩沖區中輸入數據
sendbuffer.put(sendText.getBytes());
//將緩沖區各標志復位,因為向里面put了數據標志被改變要想從中讀取數據發向服務器,就要復位
sendbuffer.flip();
//輸出到通道
client.write(sendbuffer);
System.out.println(
"服務器端向客戶端發送數據--:"
+sendText);
client.register(selector, SelectionKey.OP_READ);
}
}
/**
* @param args
* @throws IOException
*/
public
static
void main(String[] args)
throws IOException {
// TODO Auto-generated method stub
int port
=
8888;
NIOServer server
=
new NIOServer(port);
server.listen();
}
}
