java NIO服務端和客戶端程式碼實現
阿新 • • 發佈:2019-02-16
- package cn.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服務端
- * @author 小路
- */
- 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
- */
- @SuppressWarnings("unchecked")
- public void listen() throws IOException {
- System.out.println("服務端啟動成功!");
- // 輪詢訪問selector
- while (true) {
- //當註冊的事件到達時,方法返回;否則,該方法會一直阻塞
- selector.select();
- // 獲得selector中選中的項的迭代器,選中的項為註冊的事件
- Iterator ite = this.selector.selectedKeys().iterator();
- while (ite.hasNext()) {
- SelectionKey key = (SelectionKey) ite.next();
- // 刪除已選的key,以防重複處理
- ite.remove();
- // 客戶端請求連線事件
- if (key.isAcceptable()) {
- ServerSocketChannel server = (ServerSocketChannel) key
- .channel();
- // 獲得和客戶端連線的通道
- SocketChannel channel = server.accept();
- // 設定成非阻塞
- channel.configureBlocking(false);
- //在這裡可以給客戶端傳送資訊哦
- channel.write(ByteBuffer.wrap(new String("向客戶端傳送了一條資訊").getBytes()));
- //在和客戶端連線成功之後,為了可以接收到客戶端的資訊,需要給通道設定讀的許可權。
- channel.register(this.selector, SelectionKey.OP_READ);
- // 獲得了可讀的事件
- } else if (key.isReadable()) {
- read(key);
- }
- }
- }
- }
- /**
- * 處理讀取客戶端發來的資訊 的事件
- * @param key
- * @throws IOException
- */
- public void read(SelectionKey key) throws IOException{
- // 伺服器可讀取訊息:得到事件發生的Socket通道
- SocketChannel channel = (SocketChannel) key.channel();
- // 建立讀取的緩衝區
- ByteBuffer buffer = ByteBuffer.allocate(10);
- channel.read(buffer);
- byte[] data = buffer.array();
- String msg = new String(data).trim();
- System.out.println("服務端收到資訊:"+msg);
- ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes());
- channel.write(outBuffer);// 將訊息回送給客戶端
- }
- /**
- * 啟動服務端測試
- * @throws IOException
- */
- public static void main(String[] args) throws IOException {
- NIOServer server = new NIOServer();
- server.initServer(8000);
- server.listen();
- }
- }