Java review--NIO例項:實現服務端和客戶端的簡單通訊

ZeroWM發表於2016-07-30


客戶端程式碼:

package 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 =1;
	private int blockSize=4096;
	private ByteBuffer sendbuffer =ByteBuffer.allocate(blockSize);//傳送資料緩衝區
	private ByteBuffer receivebuffer =ByteBuffer.allocate(blockSize);//接收資料緩衝區
	private Selector selector;//選擇器
	
	
	public NIOServer(int port) throws IOException{
		ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
		//設定是否組阻塞
		serverSocketChannel.configureBlocking(false);
		//建立客戶端和服務端的socket.socket網路套接字,用來向網路傳送請求,或者應答請求。
		ServerSocket serverSocket=serverSocketChannel.socket();
		//繫結socket地址,IP埠
		serverSocket.bind(new InetSocketAddress(port));
		//開啟篩選器
		selector=Selector.open();
		
		// 將選擇器繫結到監聽通道,只有非阻塞通道才可以註冊選擇器.並在註冊過程中指出該通道可以進行Accept操作,返回key
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
		System.out.println("Server start ->"+port);
	}
	
	//NIOServer的監聽事件
	public void listen() throws IOException{
		while(true){
			selector.select();
			Set<SelectionKey> selectionKeys=selector.selectedKeys();
			Iterator<SelectionKey> itetor=selectionKeys.iterator();
			while(itetor.hasNext()){
				//負責多執行緒併發的安全的key
				SelectionKey selectionKey=itetor.next();
				itetor.remove();
				//業務邏輯
				handleKey(selectionKey);
			}
		}
	}
	
	
	//業務邏輯
	public void handleKey(SelectionKey selectionKey) throws IOException{
		//服務端監聽通道
		ServerSocketChannel server=null;
		SocketChannel client=null;
		String reciveText;
		String sendText;
		int count=0;
		if(selectionKey.isAcceptable()){
			//服務端接收客戶端資訊
			server=(ServerSocketChannel)selectionKey.channel();
			client=server.accept();
			client.configureBlocking(false);
			client.register(selector, selectionKey.OP_READ);
		}else if(selectionKey.isReadable()){
			//服務端讀取客戶端資訊
			client =(SocketChannel)selectionKey.channel();
			count =client.read(receivebuffer);
			if(count>0){
				reciveText =new String(receivebuffer.array(),0,count);
				System.out.println("服務端接收到客戶端的資訊:"+reciveText);
				client.register(selector,selectionKey.OP_WRITE);
			}
		}else if (selectionKey.isWritable()){
			//服務端傳送資料給客戶端
			sendbuffer.clear();
			client=(SocketChannel)selectionKey.channel();
			sendText="mag send to client:"+flag++;
			sendbuffer.put(sendText.getBytes());
			sendbuffer.flip();
			client.write(sendbuffer);
			System.out.println("服務端傳送資料給客戶端:"+sendText);
			
		}
		
	}
	
	public static void main(String[] args) throws IOException {
		int port =7080;
		NIOServer server =new NIOServer(port);
		server.listen();
	}
	
	
	
}




服務端程式碼:

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.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NIOClient {
	private static  int flag =1;
	private static int blockSize=4096;
	private static ByteBuffer sendbuffer =ByteBuffer.allocate(blockSize);//傳送資料緩衝區
	private static  ByteBuffer receivebuffer =ByteBuffer.allocate(blockSize);//接收資料緩衝區
	
	//Socket地址:ip+埠
	private final static InetSocketAddress serverAddress=new InetSocketAddress("127.0.0.1",7080);
	
	public static void main(String[] args) throws IOException {
		//開啟通道
		SocketChannel socketChannel=SocketChannel.open();
		//通道設定成非阻塞模式
		socketChannel.configureBlocking(false);
		//開啟篩選器
		Selector selector =Selector.open();
		//註冊選擇器
		socketChannel.register(selector, SelectionKey.OP_CONNECT);
		socketChannel.connect(serverAddress);
		
		Set<SelectionKey> selectionKeys;
		Iterator<SelectionKey> iterator;
		SelectionKey selectionKey;
		SocketChannel client;
		String receiveTest;
		String sendText;
		int count=0;		
		while(true){
			selectionKeys =selector.selectedKeys();
			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);
					
				}if(selectionKey.isReadable()){
						client=(SocketChannel)selectionKey.channel();
						receivebuffer.clear();
						count=client.read(receivebuffer);
						if(count>0){
							receiveTest =new String(receivebuffer.array(),0,count);
							System.out.println("客戶端接收到服務端的資料:"+receiveTest);
							client.register(selector,SelectionKey.OP_WRITE);
							
						}
				}if(selectionKey.isWritable()){
					sendbuffer.clear();
					client=(SocketChannel)selectionKey.channel();
					sendText="Msg from client--->"+flag++;
					sendbuffer.put(sendText.getBytes());
					sendbuffer.flip();
					client.write(sendbuffer);
					System.out.println("客戶端傳送方資料給服務端:"+sendText);
					client.register(selector, SelectionKey.OP_READ);
					
				}
				}
			
			selectionKeys.clear();
			}
		}
	}



相關文章