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();
		}

	}

}


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