看完FEIQQ--Netty版本的源码后,接下来用NIO来实现程序的功能。
软件原理:
程序主要运用了mysql数据库技术进行数据处理,NIO技术实现客户端与服务器交互。NIO是非阻塞异步IO,是基于缓存区的IO。
实现思路:
程序在启动时会调用Server类和Client类的start方法,start方法包含了NIO的使用,包括以下几步:
1. 首先SocketChannel.open()方法打开信息通道。
2. 调用configureBlocking方法,设置非阻塞模式。
3. 调用connect()或bind方法绑定ip。
4. 调用Selector.open()方法打开多路复用器。
5. 利用register方法把通道注册到多路复用器上。
6.将Selector.select()放入while(true)循环中,一直监听,对获取的SelectionKey进行处理。
结构示意图:
代码实现:
sc=SocketChannel.open();//打开信道
sc.configureBlocking(false);//设置为非阻塞模式
sc.connect(new InetSocketAddress(Constants.SERVER_IP,Constants.SERVER_PORT));//连接服务端
selector = Selector.open();//必须打开
//将当前客户端注册到多路复用器上
sc.register(selector, SelectionKey.OP_CONNECT);
new Thread(){
public void run(){
while(true){//一直循环
try {
selector.select();//多路复用器开始监听
//获取已经注册在多了复用器上的key通道集
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
//遍历
while (keys.hasNext()) {
SelectionKey key = keys.next();//获取key
//如果是有效的
if(key.isValid()){
SocketChannel socket=(SocketChannel) key.channel();
if(key.isConnectable()){
if(socket.finishConnect()){
connect(key);
System.out.println("客户端连接");
}
}
// 如果为可读状态,读取服务端返回的数据
if(key.isReadable()){
read(key);
}
}
//从容器中移除处理过的key
keys.remove();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
实现效果:
心得体会:
NIO是基于通道(Channel)和缓冲区(Buffer)的流,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中,是异步,非阻塞的IO,NIO提供的Selector可以使一个线程管理多个通道,有效节省了线程,但是NIO的编码复杂,需要处理半包和粘包问题。
但通过上面的步骤能看出,与使用Netty相比,Nio的操作步骤更多,更复杂,Nio的功能也比较少。当然,Netty是基于NIO的网路框架,Netty的功能用NIO也可以实现,不过需要自己实现。
{{ cmt.username }}
{{ cmt.content }}
{{ cmt.commentDate | formatDate('YYYY.MM.DD hh:mm') }}