NIO通信

今天練習了一下以前學過的NIO編程,寫了一個NIO 通信的小示例,希望以後看到這個案例時,可以理解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;
import java.util.Set;
/**
 * 進行使用Nio套接字來開發我們的tomcat的的服務器的連接操作
 * @author Administrator
 * 通過調用open方法得到一個ServerSocketChannel通道
 * 但是這個通道還沒有被綁定地址通過調用調用bind()方法來進行綁定數據
 *
 */
public class SocketServer {
	
	public static void start(){
		try {
			//先進行創建一個轉詢容器
			Selector sel=Selector.open(); 
			//通過open的方法得到nio的套接字通道
			ServerSocketChannel server=ServerSocketChannel.open();
			//進行綁定我們的地址
			server.bind(new InetSocketAddress("localhost",8080),2500);
			//進行設置非阻塞的操作的方法
			server.configureBlocking(false);
			//先進行把我們SSC註冊入SelectKey容器當中,同時這個註冊服務器通道的感興趣事件(這個事件有4種)
			server.register(sel, SelectionKey.OP_ACCEPT);
			while(true){
				//進行輪詢的桃選已發生的操作感興趣事件,放入一個selected key集合當中
				sel.select(); //是一個阻塞的操作的方法,是一個集合
				//進行得到精選key的集合
				Set<SelectionKey> set=sel.selectedKeys();
				//進行遍歷所以的發生的key
				Iterator<SelectionKey> it=set.iterator();
				while(it.hasNext()){
					//得到桃選的key
					SelectionKey key=it.next();
					//判斷這個key是否爲服務器的連接方法,如果是則進行連接,得到客戶端的通道
					if(key.isAcceptable()){
						
						ServerSocketChannel sch=(ServerSocketChannel)key.channel();
						//進行接收請求然後進行註冊
						SocketChannel ch=sch.accept();
						
						//這個也要進行配置我們非阻塞模式
						ch.configureBlocking(false);
						//然後進行客戶端的註冊的感興趣事件
						ch.register(sel,SelectionKey.OP_CONNECT|SelectionKey.OP_READ|SelectionKey.OP_WRITE);
					}
					//如果這個是一個讀請求,那麼則
					if(key.isReadable()){
						//進行得到客戶端的通道
						SocketChannel sc=(SocketChannel) key.channel();
						//進行讀取數據
						String str=readFormClient(sc);
						System.out.println("from client: "+str);
					}
					if(key.isWritable()){
						ByteBuffer buffer=ByteBuffer.allocate(1024);
						buffer.put("數據從服務器發送....".getBytes());
						//進行寫數據
						SocketChannel sc=(SocketChannel)key.channel();
						buffer.flip();
						sc.write(buffer);
						buffer.clear();
					}
					
					if(key.isConnectable()){
						System.out.println("client connectable");
					}
				}
				//進行移除這個key數據
				it.remove();
			
			}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
	
	public static String readFormClient(SocketChannel sc){
		ByteBuffer buffer=ByteBuffer.allocate(1024);
		String str=null;
		try {
			int len=sc.read(buffer);
			if(len==-1){
			   System.out.println("from client:數據已經讀取完成...");
			}else if(len>0) {
				//進行壓縮
				buffer.flip();
				str=new String(buffer.array(),0,buffer.limit());
				buffer.clear();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return str.trim();
	}
}


服務器的main方法如下:

/**
 * 我們的NIO的啓動類
 * @author Administrator
 *
 */
public class Bootstrap {
	
	public static void main(String[] args) {		
		//網絡Socket通信
		SocketServer.start();
	}
	
}

客戶端代碼如下:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SocketChannel;

public class SocketChannelClient {

	public static void main(String[] args) {
		// 先註冊輪詢
		try {
			//Selector selector = Selector.open();
			ByteBuffer buffer = ByteBuffer.allocate(1024);

			// 創建一個輸入流通道
			ReadableByteChannel incha = Channels.newChannel(System.in);
			// 進行向服務器連接
			SocketChannel sc = null;

			sc = SocketChannel.open(new InetSocketAddress("localhost", 8080));
			sc.configureBlocking(false);
			// 進行連接操作
			// sc.connect(new InetSocketAddress("localhsot",8080));

			while (!sc.finishConnect()) {

			}
			// 進行從客戶端輸入數據,然後輸出數據
			while (true) {
				incha.read(buffer);
				buffer.flip();
				sc.write(buffer);
				buffer.clear();
			}

		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

	}

}

客戶端代碼二如下:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class SocketChannelClient2 {

	public static void main(String[] args) {
		
		try {
			// 先註冊輪詢
			Selector sel = Selector.open();
			ByteBuffer buffer = ByteBuffer.allocate(1024);

			// 創建一個輸入流通道
			ReadableByteChannel incha = Channels.newChannel(System.in);
			// 進行向服務器連接
			SocketChannel sc = null;

			sc = SocketChannel.open(new InetSocketAddress("localhost", 8080));
			sc.configureBlocking(false);
			while (!sc.finishConnect()) {

			}
			// 進行連接操作
			// sc.connect(new InetSocketAddress("localhsot",8080));
			//進行註冊
			sc.register(sel,SelectionKey.OP_CONNECT|SelectionKey.OP_READ|SelectionKey.OP_WRITE);

			// 進行從客戶端輸入數據,然後輸出數據
			while (true) {
				//進行挑選操作
				sel.select();
				Iterator<SelectionKey> it=sel.selectedKeys().iterator();
				while(it.hasNext()){
					SelectionKey key=it.next();
					if(key.isConnectable()){
						//進行連接服務器
						System.out.println("連接服務器...");
					}
					if(key.isWritable()){
						//得到通道
						sc=(SocketChannel) key.channel();
						System.out.println("輸入你要發送的數據:");
						incha.read(buffer);
						buffer.flip();
						sc.write(buffer);
						buffer.clear();
					}
					
					if(key.isReadable()){
						//進行讀取數據通道
						sc=(SocketChannel) key.channel();
						//buffer.clear();
						int len=sc.read(buffer);
						if(len==-1){
							System.out.println("到文件未了...");
						}else if(len>0){
							buffer.flip();
							String str=new String(buffer.array(),0,buffer.limit()).trim();
							buffer.clear();
							System.out.println("from server:"+str);
						}
					}
					it.remove();
				}
				
				
			}

		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

	}

}


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