1、OIO與NIO程式碼示例比較
阿新 • • 發佈:2019-01-24
- 傳統socket服務端,程式碼示例
package OIO;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 傳統socket服務端
* */
public class OioServer {
@SuppressWarnings ("resource")
public static void main(String[] args) throws Exception {
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
//建立socket服務,監聽10101埠
ServerSocket server=new ServerSocket(10101);
System.out.println("伺服器啟動!");
while(true){
//獲取一個套接字(阻塞)
final Socket socket = server.accept();
System.out.println("來個一個新客戶端!");
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
//業務處理
handler(socket);
}
});
}
}
/**
* 讀取資料
* @param socket
* @throws Exception
*/
public static void handler(Socket socket){
try {
byte[] bytes = new byte[1024];
InputStream inputStream = socket.getInputStream();
while(true){
//讀取資料(阻塞)
int read = inputStream.read(bytes);
if(read != -1){
System.out.println(new String(bytes, 0, read));
}else{
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
System.out.println("socket關閉");
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- NIO服務端,程式碼示例
package 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.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
/**
* NIO服務端
*/
public class NIOServer {
// 通道管理器
private Selector selector;
/**
* 獲得一個ServerSocket通道,並對該通道做一些初始化的工作
*
* @param port
* 繫結的埠號
* @throws IOException
*/
public void initServer(int port) throws IOException {
// 獲得一個ServerSocket通道
ServerSocketChannel serverChannel = ServerSocketChannel.open();
// 設定通道為非阻塞
serverChannel.configureBlocking(false);
// 將該通道對應的ServerSocket繫結到port埠
serverChannel.socket().bind(new InetSocketAddress(port));
// 獲得一個通道管理器
this.selector = Selector.open();
// 將通道管理器和該通道繫結,併為該通道註冊SelectionKey.OP_ACCEPT事件,註冊該事件後,
// 當該事件到達時,selector.select()會返回,如果該事件沒到達selector.select()會一直阻塞。
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
}
/**
* 採用輪詢的方式監聽selector上是否有需要處理的事件,如果有,則進行處理
*
* @throws IOException
*/
public void listen() throws IOException {
System.out.println("服務端啟動成功!");
// 輪詢訪問selector
while (true) {
// 當註冊的事件到達時,方法返回;否則,該方法會一直阻塞
selector.select();
//selector.select(10000);
//selector.wakeup();
// 獲得selector中選中的項的迭代器,選中的項為註冊的事件
Iterator<?> ite = this.selector.selectedKeys().iterator();
while (ite.hasNext()) {
SelectionKey key = (SelectionKey) ite.next();
// 刪除已選的key,以防重複處理
ite.remove();
handler(key);
}
}
}
/**
* 處理請求
*
* @param key
* @throws IOException
*/
public void handler(SelectionKey key) throws IOException {
// 客戶端請求連線事件
if (key.isAcceptable()) {
handlerAccept(key);
// 獲得了可讀的事件
} else if (key.isReadable()) {
handelerRead(key);
}
}
/**
* 處理連線請求
*
* @param key
* @throws IOException
*/
public void handlerAccept(SelectionKey key) throws IOException {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
// 獲得和客戶端連線的通道
SocketChannel channel = server.accept();
// 設定成非阻塞
channel.configureBlocking(false);
// 在這裡可以給客戶端傳送資訊哦
System.out.println("新的客戶端連線");
// 在和客戶端連線成功之後,為了可以接收到客戶端的資訊,需要給通道設定讀的許可權。
channel.register(this.selector, SelectionKey.OP_READ);
}
/**
* 處理讀的事件
*
* @param key
* @throws IOException
*/
public void handelerRead(SelectionKey key) throws IOException {
// 伺服器可讀取訊息:得到事件發生的Socket通道
SocketChannel channel = (SocketChannel) key.channel();
// 建立讀取的緩衝區
ByteBuffer buffer = ByteBuffer.allocate(1024);
int read = channel.read(buffer);
if(read > 0){
byte[] data = buffer.array();
String msg = new String(data).trim();
System.out.println("服務端收到資訊:" + msg);
//回寫資料
ByteBuffer outBuffer = ByteBuffer.wrap("好的".getBytes());
channel.write(outBuffer);// 將訊息回送給客戶端
}else{
System.out.println("客戶端關閉");
key.cancel();
}
}
/**
* 啟動服務端測試
*
* @throws IOException
*/
public static void main(String[] args) throws IOException {
NIOServer server = new NIOServer();
server.initServer(8000);
server.listen();
}
}