NIO
Posted theqi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NIO相关的知识,希望对你有一定的参考价值。
客户端代码
public static void client()
{
ByteBuffer buffer = ByteBuffer.allocate(1024);//给buffer缓冲区分配空间
SocketChannel socketChannel = null;
try
{
socketChannel = SocketChannel.open();//打开socketChannel
socketChannel.configureBlocking(false);//配置这个信道为非阻塞信道
socketChannel.connect(new InetSocketAddress(InetAddress.getLocalHost(),8080));//连接服务器
if(socketChannel.finishConnect())//用来确认通道连接已经建立的
{
int i=0;
while(true)
{
TimeUnit.SECONDS.sleep(1);//延时一秒
String info = "I‘m "+i+++"-th information from client";
buffer.clear();//将buffer中没读的数据遗忘掉(limit又会回到capacity)
buffer.put(info.getBytes());//将字符串存如buffer中
//调用下面这个函数会让position为0,limit为之前position的值
//这样我们只可以读出从position到limit这些位置的数据,也就是之前我们写的数据
buffer.flip();
while(buffer.hasRemaining()){//判断当前元素是否在限制范围内(positon是否limit)
System.out.println(buffer);
socketChannel.write(buffer);//将buffer中的数据写如socketChannel中
}
}
}
}
catch (IOException | InterruptedException e)
{
e.printStackTrace();
}
finally{
try{
if(socketChannel!=null){
socketChannel.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
服务器代码:
public class Main
{
private static final int BUF_SIZE=1024;
private static final int PORT = 8080;
private static final int TIMEOUT = 3000;
public static void main(String[] args)
{
selector();
}
public static void handleAccept(SelectionKey key) throws IOException
{
ServerSocketChannel ssChannel = (ServerSocketChannel)key.channel();//获取发生网络事件的ssc
SocketChannel sc = ssChannel.accept();//通过accept获取SocketChannel
sc.configureBlocking(false);
//将sc注册到selector中,注册读事件,同时附加参数为一个申请的1024的buffer空间
sc.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocateDirect(BUF_SIZE));
}
public static void handleRead(SelectionKey key) throws IOException{
SocketChannel sc = (SocketChannel)key.channel();//获取发生网络事件的sc
ByteBuffer buf = (ByteBuffer)key.attachment();//获取附加参数
long bytesRead = sc.read(buf);//从Channel中读取数据到buffer中
while(bytesRead>0){
buf.flip();
while(buf.hasRemaining()){
System.out.print((char)buf.get());
}
System.out.println();
buf.clear();
bytesRead = sc.read(buf);//继续读取
}
if(bytesRead == -1){//客户端数据发送完毕并主动断开socket
sc.close();
}
}
public static void handleWrite(SelectionKey key) throws IOException{
ByteBuffer buf = (ByteBuffer)key.attachment();
buf.flip();
SocketChannel sc = (SocketChannel) key.channel();
while(buf.hasRemaining()){
sc.write(buf);//通过buffer写入数据到信道中
}
buf.compact();//将所有处理的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。
//limit属性依然像clear()方法一样,设置成capacity
}
public static void selector() {
Selector selector = null;//与其一起使用的通道一定是非阻塞的(FileChannel就不行)
ServerSocketChannel ssc = null;
try{
selector = Selector.open();//打开selector
ssc= ServerSocketChannel.open();//打开SSC(客户端那边是SocketChannel)
ssc.socket().bind(new InetSocketAddress(PORT));//绑定端口号
ssc.configureBlocking(false);//设置非阻塞
SelectionKey s = ssc.register(selector, SelectionKey.OP_ACCEPT);// 选择注册什么事件到selector中
while(true){
if(selector.select(TIMEOUT) == 0){
System.out.println("==");
continue;
}
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();//遍历发生事件的sK
while(iter.hasNext()){
SelectionKey key = iter.next();
if(key.isAcceptable()){
handleAccept(key);
}
if(key.isReadable()){
handleRead(key);
}
if(key.isWritable() && key.isValid()){
handleWrite(key);
}
if(key.isConnectable()){
System.out.println("isConnectable = true");
}
iter.remove();
}
}
}catch(IOException e){
e.printStackTrace();
}finally{
try{
if(selector!=null){
selector.close();
}
if(ssc!=null){
ssc.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}
以上是关于NIO的主要内容,如果未能解决你的问题,请参考以下文章
Netty——NIO(Selector处理read事件)代码示例