http://xm-king.iteye.com/blog/766330最近一直在忙着JAVA NIO的知識,花了一下午的時間,總算寫出了一個可以運作的程式,廢話少說,上代碼!
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
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 selectionKeys = selector.selectedKeys();
Iterator 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);
}
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
int port = 8888;
NIOServer server = new NIOServer(port);
server.listen();
}
}
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class NIOClient {
private static int flag = 0;
private static int BLOCK = 4096;
private static ByteBuffer sendbuffer = ByteBuffer.allocate(BLOCK);
private static ByteBuffer receivebuffer = ByteBuffer.allocate(BLOCK);
private final static InetSocketAddress SERVER_ADDRESS = new InetSocketAddress(
"localhost", 1111);
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// 打開socket通道
SocketChannel socketChannel = SocketChannel.open();
// 設定為非阻塞方式
socketChannel.configureBlocking(false);
// 打開選擇器
Selector selector = Selector.open();
// 注冊連接配接服務端socket動作
socketChannel.register(selector, SelectionKey.OP_CONNECT);
// 連接配接
socketChannel.connect(SERVER_ADDRESS);
// 配置設定緩沖區大小記憶體
Set selectionKeys;
Iterator iterator;
SelectionKey selectionKey;
SocketChannel client;
String receiveText;
String sendText;
int count=0;
while (true) {
//選擇一組鍵,其相應的通道已為 I/O 操作準備就緒。
//此方法執行處于阻塞模式的選擇操作。
selector.select();
//傳回此選擇器的已選擇鍵集。
selectionKeys = selector.selectedKeys();
//System.out.println(selectionKeys.size());
iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
selectionKey = iterator.next();
if (selectionKey.isConnectable()) {
System.out.println("client connect");
client = (SocketChannel) selectionKey.channel();
// 判斷此通道上是否正在進行連接配接操作。
// 完成套接字通道的連接配接過程。
if (client.isConnectionPending()) {
client.finishConnect();
System.out.println("完成連接配接!");
sendbuffer.clear();
sendbuffer.put("Hello,Server".getBytes());
sendbuffer.flip();
client.write(sendbuffer);
}
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 client--" + (flag++);
sendbuffer.put(sendText.getBytes());
//将緩沖區各标志複位,因為向裡面put了資料标志被改變要想從中讀取資料發向伺服器,就要複位
sendbuffer.flip();
client.write(sendbuffer);
System.out.println("用戶端向伺服器端發送資料--:"+sendText);
client.register(selector, SelectionKey.OP_READ);
}
}
selectionKeys.clear();
}
}
}