NIO通信分析

一、传统Socket通信的分析
1. 传统的socket通信是阻塞式通信,阻塞点有两个:
服务端接收客户端请求: server.accept();
服务端读入客户端请求:inputStream.read(bytes);
2. 单线程情况下,一个socket只能处理一个来自客户端的请求,只有当客户端的请求处理,
完成之后才会释放这个线程;
如果要接受来自多个客户端的请求,那就只能使用线程池;
采用线程池可以提高效率,但也只是适合处理短连接,如果是长连接的话,会产生大量的线程,
系统无法担负。

二、NIO的分析
1. NIO是非阻塞式的通信,可以同时和多个客户端进行通信;
当接受到一个客户端的请求后,通道管理器将其接收,然后对于接收到的请求直接扔给后续处理,并不会阻塞新来的客户端请求。
2. NIO服务器端代码如下:

package com.itmuch.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 NIOServerPra {

//NIO通道管理器
private Selector selector;
//服务器端的初始化
private void initServer(int port) throws IOException {
//获取一个和客户端进行通信的通道
ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
//设置通道为非阻塞
serverSocketChannel.configureBlocking(false);
//将通道对应的servrSocket绑定端口号port
serverSocketChannel.socket().bind(new InetSocketAddress(port));
//获取通道管理器
this.selector=Selector.open();
//将通道管理器和通道进行绑定,并为通道管理器注册SelectionKey.OP_ACCEPT事件,如果是该事件,则
//继续进行,否则阻塞
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
}
/**
* 采用轮询的方式进行监听,查看是否有从客户端来的请求
* @author
* @throws IOException
*/
private void listen() throws IOException {
System.out.println("服务端启动,查看是否有服务");
while(true) {
//有接收事件到来,继续进行
selector.select();
//获取selector中选中的项的迭代器,选中的项是注册的事件
Iterator ite=selector.selectedKeys().iterator();
while(ite.hasNext()) {
SelectionKey key=(SelectionKey) ite.next();
//将选中的项进行处理,同时移除该事件
ite.remove();
handler(key);
}
}
}

/**
* 对获取到的事件进行处理
* @author
* @param key
* @throws IOException
*/
private void handler(SelectionKey key) throws IOException {
//处理Accept类型事件
if(key.isAcceptable()) {
handlerAccept(key);
}
//处理read类型事件
if(key.isReadable()) {
handlerRead(key);
}
}
/**
* accept类型事件处理,用于建立服务器端和客户端的通信链路
* @author
* @param key
* @throws IOException
*/
private void handlerAccept(SelectionKey key) throws IOException {
ServerSocketChannel serverChannel=(ServerSocketChannel) key.channel();
//获得和客户端的连接
SocketChannel channel=serverChannel.accept();
//将连接设置为非阻塞的
channel.configureBlocking(false);
System.out.println("新的客户端和服务端连接建立 ");
//在跟客户端的连接建立成功后,为了读取客户端的信息,需要给客户端设置读的权限
channel.register(selector, SelectionKey.OP_READ);
}

/**
* read事件处理,处理客户端发送来的信息
* @author
* @param key
* @throws IOException
*/
private void handlerRead(SelectionKey key) throws IOException {
//服务器读取到的消息,得到事件发送的通道
SocketChannel channel=(SocketChannel) key.channel();
//设置字节容器
ByteBuffer buffer=ByteBuffer.allocate(1024);
int read=channel.read(buffer);
if(read>0) {
byte[] data=buffer.array();
String msg=new String(data).trim();
System.out.println("msg: "+msg);
//回写数据
ByteBuffer outBuffer=ByteBuffer.wrap("ok".getBytes());
channel.write(outBuffer);
}else {
System.out.println("客户端关闭");
key.cancel();
}
}

public static void main(String[] args) throws IOException {
NIOServerPra server=new NIOServerPra();
server.initServer(8001);
server.listen();
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值