nio知識

1)原理

http://www.cnblogs.com/rollenholt/archive/2011/09/29/2195730.html


2)例子

http://xm-king.iteye.com/blog/766330


3)比較一下


原有IO寫法:

package test.socket;


import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;


public class Server {


public void startServer(int port) {


DataInputStream in = null;
OutputStream out = null;
BufferedReader reader = null;
try {
ServerSocket server = new ServerSocket(port);
// while (true) {
Socket client = server.accept();
in = new DataInputStream(client.getInputStream());


// 獲取客戶端請求信息
reader = new BufferedReader(
new InputStreamReader(in));

// 執行到此出現toString() unavailable - no suspended threads
String line = null;
if(reader!=null){
line = reader.readLine();
}

if (line != null && !"".equals(line)) {
System.out.println(line);
} else {
System.out.println("null or empty");
}

// Thread.sleep(1000);
//server-->client
out = client.getOutputStream();
out.write("server response to client\n".getBytes());
out.flush();
//}
// client.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}


public static void main(String[] args) {
Server server = new Server();
server.startServer(8888);
}
}


package test.socket;


import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;


public class Client {


public static void main(String[] args) {
OutputStream out = null;
DataInputStream in = null;
BufferedReader reader = null;
try {
Socket client = new Socket("localhost", 8888);


out = client.getOutputStream();
out.write("request to server\n".getBytes());
out.flush();

// Thread.sleep(2000);
in = new DataInputStream(client.getInputStream());
reader = new BufferedReader(
new InputStreamReader(in));
System.out.println(">>>>>"+reader.readLine());


}catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


NIO寫法:

package test.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(String ip, int port) throws IOException {

// 打開服務器套接字通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

// 服務器配置爲非阻塞
serverSocketChannel.configureBlocking(false);

// 檢索與此通道關聯的服務器套接字
ServerSocket serverSocket = serverSocketChannel.socket();

// 進行服務的綁定
serverSocket.bind(new InetSocketAddress(ip, 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("127.0.0.1", port);
server.listen();
}
}


package test.nio;


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", 8888);


public static void main(String[] args) throws IOException {


// 打開socket通道
SocketChannel socketChannel = SocketChannel.open();


// 設置爲非阻塞方式
socketChannel.configureBlocking(false);


// 打開選擇器
Selector selector = Selector.open();


// 註冊連接服務端socket動作
socketChannel.register(selector, SelectionKey.OP_CONNECT);


// 連接
socketChannel.connect(SERVER_ADDRESS);


// 分配緩衝區大小內存
Set<SelectionKey> selectionKeys;
Iterator<SelectionKey> iterator;
SelectionKey selectionKey;
SocketChannel client;
String receiveText;
String sendText;
int count = 0;


// for (int i = 0; i < 100; i++) {
// 選擇一組鍵,其相應的通道已爲 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();
// }
}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章