网络编程复习(三):NIO模式

关于NIO,就是同步非阻塞,虽然效率会提高,但实现起来的有点麻烦,所以实际开发中用的很少,更多的是用Netty框架使用网络Socket,Netty其实是对JDK的nio的一个优化封装,实现起来更加方便,后续也将会介绍,下面看看流程图解:


client端:

package 网络编程_NIO;

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

public class Client {
	public static void main(String[] args) {
		//定义socket连接的地址与端口
		InetSocketAddress address = new InetSocketAddress("127.0.0.1",8888);
		//通道
		SocketChannel channel = null;
		//缓冲区
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		try {
			//打开通道
			channel = SocketChannel.open();
			//连接地址
			channel.connect(address);
			while(true){
				byte[] bys = new byte[1024];
				//控制台读取数据1024字节
				System.in.read(bys);
				//数据放入缓冲区
				buffer.put(bys);
				//复位
				buffer.flip();
				//通道将缓冲区数据写给服务端
				channel.write(buffer);
				//清空缓冲区
				buffer.clear();
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(channel!=null){
				try {
					channel.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

server端:

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;

public class Server implements Runnable{

	private Selector selector;
	private ByteBuffer readerBuffer = ByteBuffer.allocate(1024);
	//private ByteBuffer writerBuffer = ByteBuffer.allocate(1024);
	public  Server(int port) {
		try {
			//打开多路复用器
			this.selector = Selector.open();
			//打开连接通道
			ServerSocketChannel socketChannel = ServerSocketChannel.open();
			//设置为非阻塞模式
			socketChannel.configureBlocking(false);
			//通道绑定端口监听
			socketChannel.bind(new InetSocketAddress(port));
			//通道注册到多路复用器上
			socketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
			System.out.println("Server started..."+port);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	@Override
	public void run() {
		while(true){
			try {
				//多路复用器开始监听
				this.selector.select();
				//返回多路复用器选择的结果集
				Iterator<SelectionKey> keys = this.selector.selectedKeys().iterator();
				//开始遍历
				while(keys.hasNext()){
					//获得选择的第一个元素
					SelectionKey key = keys.next();
					//将选择的元素从容器中移除
					keys.remove();
					//如果元素可用
					if(key.isValid()){
						//如果为阻塞状态
						if(key.isAcceptable()){
							this.accept(key);
						}
						//可读
						if(key.isReadable()){
							this.read(key);
						}
						//可写
						if(key.isWritable()){
							this.writer(key);
						}
					}
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	private void writer(SelectionKey key) {
		/*this.writerBuffer.clear();
		SocketChannel channel  = (SocketChannel) key.channel();
		byte[] bys = new String("服务端已经接受到你的数据").getBytes();
		writerBuffer.put(bys);
		writerBuffer.flip();
		try {
			channel.write(writerBuffer);
			writerBuffer.clear();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
	}
	private void read(SelectionKey key) {
		try {
			this.readerBuffer.clear();
			SocketChannel channel = (SocketChannel) key.channel();
			int count = channel.read(readerBuffer);
			if(count == -1){
				key.channel().close();
				key.cancel();
				return;
			}
			this.readerBuffer.flip();
			byte[] bys = new byte[this.readerBuffer.remaining()];
			this.readerBuffer.get(bys);
			String body = new String(bys).trim();
			System.out.println("Server"+body);
			//channel.register(this.selector, SelectionKey.OP_WRITE);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	private void accept(SelectionKey key) {
		try {
			ServerSocketChannel socketChannel = (ServerSocketChannel) key.channel();
			SocketChannel channel = socketChannel.accept();
			channel.configureBlocking(false);
			//阻塞状态变为可读状态
			channel.register(this.selector, SelectionKey.OP_READ);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	public static void main(String[] args) {
		new Thread(new Server(8888)).start();
	}
}

这里我并没有实现服务端向客户端写数据,因为这种情况客户端也像一个服务端了,实现起来和server端代码很相似,加一个Selector就行了,这里感觉很麻烦,所以没有实现,有兴趣的朋友可以试下。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值