服务端程序:
package com.fyd.nio;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
/***
* @Author付亚东
* @Date 2020/5/26 21:59
****/
public class NIOServer {
public static void main(String[] args) throws Exception{
//创建ServerSocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//的到一个Selector
Selector selector = Selector.open();
//监听一个端口绑定
InetSocketAddress inetSocketAddress = new InetSocketAddress(6666);
serverSocketChannel.socket().bind(inetSocketAddress);
//设置为非阻塞
serverSocketChannel.configureBlocking(false);
//把serverSocketChannel注册到 selector 关心事件为 OP_ACCEPT
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//循环等待客户端链接
while (true){
//这里等待1秒,如果没有事件发生,下一次循环
if(selector.select(1000)==0){
System.out.println("服务器等待了1秒,无连接");
continue;
}
//如果返回的不是0,有事件发生
//获取到相关的selectionKeys集合
//1、如果返回大于0,则获取到关注的事件
//2、selector.selectedKeys 返回关注事件的集合
// 通过selectionKeys反向获取通道
Set<SelectionKey> selectionKeys = selector.selectedKeys();
//遍历,使用迭代器
Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
while (selectionKeyIterator.hasNext()){
//获取到selectionKey
SelectionKey selectionKey = selectionKeyIterator.next();
//根据这个key对应的通道发生的事件做不同的处理
if(selectionKey.isAcceptable()){//如果是这个事件OP_ACCEPT,代表有新的客户端链接
//给该客户端生成一个SocketChannel
//因为上边的判断,判定此次就是客户端链接,所以这里不会阻塞
SocketChannel socketChannel = serverSocketChannel.accept();
//设置为非阻塞
socketChannel.configureBlocking(false);
System.out.println("客户端链接成功,"+socketChannel.hashCode());
//将 socketChannel 也注册到selector上,关注事件为OP_READ,
// 同时给这个socketChannel关联一个buffer
socketChannel.register(selector,SelectionKey.OP_READ, ByteBuffer.allocate(1024));
}else if(selectionKey.isReadable()){//如果是这个事件OP_READ,代表有客户端数据
//通过selectionKey获取channel
SocketChannel socketChannel = (SocketChannel)selectionKey.channel();
//获取到该channel关联的buffer
ByteBuffer byteBuffer = (ByteBuffer)selectionKey.attachment();
//读取数据
socketChannel.read(byteBuffer);
System.out.println("客户端发送的数据:"+new String(byteBuffer.array()));
}
//手动从集合中移除当前的selectKey,否则会出现重复操作。多线程
selectionKeyIterator.remove();
}
}
}
}
客户端程序:
package com.fyd.nio;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
/***
* @Author付亚东
* @Date 2020/5/31 21:20
****/
public class NIOClient {
public static void main(String[] args) throws Exception{
//得到一个通道
SocketChannel socketChannel = SocketChannel.open();
//设置非阻塞模式
socketChannel.configureBlocking(false);
//提供服务器端的ip和端口
InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1",6666);
//链接服务器
if(!socketChannel.connect(inetSocketAddress)){//如果链接失败
while (!socketChannel.finishConnect()){
System.out.println("因为链接需要时间,客户端不会阻塞,可以做其他工作");
}
}
//如果链接成功,发送数据
String msg = "你好,亚东";
ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());
//发送数据
socketChannel.write(byteBuffer);
//会停在这里
System.in.read();
}
}
1、首先启动服务端,会打印如下日志:
2、然后启动客户端,服务端会打印接收到数据,1s后继续非阻塞等待
我的笔记博客版权
我的笔记博客版权