Netty的深入浅出--32.NIO实现简单网络聊天程序(上)

在之前的项目里面,我们写了服务端,然后通过telnet和nc作为客户端进行连接,接下来我们将完整的写完服务端与客户端的代码,进行数据通信。

想必大家都使用过IO写过简单了聊天程序,现在我们试着使用NIO来实现网络聊天。

在之前的项目里面我们使用的是多个channel,建立了多个端口,这次我们采用一个通道channel(一个端口)进行网络通信。但是这个和传统的IO编程不同的是,NIO实现的网络通信,只有一个线程!

首先我们要考虑到一个问题,那就是客户端连接到服务器之后通过什么来标识的呢?UUID或者是客户端的Mac地址保存到对应的channel当中。

服务端:

创建ServerSocketChannel对象,一定要记得设置为非阻塞的形式

通过ServerSocketChannel获取服务端的socket连接,并且绑定端口号

调用selector的静态方法open,获得服务端的selector对象

 现在有了serverSocketChannel对象和selector对象,一定要记住是将独立的serverSocketChannel 对象注册到selector中。

SelectionKey.OP_ACCEPT是一个事件,也就是定义了只有当触发了当前事件之后,才会调用相应的channel。而这里所对应的channel就是serverSocketChannel。

 selector:该方法是一个阻塞式方法。不断监听它所关注的selectionKey中事件发生,这个方法返回的是它所关注这个事件发生的数量。

 当selector监听到某个事件之后,就可以获取到该事件注册的所有SelectionKey事件

 现在我们针对不同的事件进行处理

如果在获取的selectionKey的集合中有Acceptable这个key说明连接成功

连接成功之后,我们可以通过selectionKey来获取相对于的channel对象。

这里我说明一下:因为我们是将channel对象注册到selector里面的,因此通过selectionKey对象来直接获取相对应的Channel对象。O(∩_∩)O感觉到是不是很腻害的样子

 既然这么腻害,那我们就去看一下.channel()这个方法的源码

返回一个SelectableChannel

而ServerSocketChannel是一个子类

返回的是一个父类型,因此我们得强制转换成一个子类型:

但是问题来说,那为什么就一定转成ServerSocketChannel就正确呢?

 因为我们在刚开始的时候将OP_ACCEPT事件注册到了serverSocketChannel上面,也就是说当前只有一个Channel将accept事件注册了,所以返回的肯定只有serverSocketChannel了!

当前的servrsocketChannel任务已经完成了(主要是启到建立连接的作用)

建立连接之后,使用的是连接之后返回的socket

也要配置 成非阻塞的,至于为什么?

这还用问,阻塞式的还得等待,也就是同步,而非阻塞式就是异步,你觉得应该用什么。

 创建以后也要注册到selector里面,至于为什么?

因为在NIO编程中,所有的channel都由selector管理,而且这里使用到的key是只读事件。

 那现在怎样才能将消息保存到服务端,然后实现消息的分发呢?

我们使用map对象来保存客户端的连接信息:

这里我们采用UUID的方法来辨别客户端:

我们将客户端连接的socketChannel保存到map中

现在判断是否建立连接已经编写完毕,现在我们就要讨论是否客户端有发送请求信息过来

获取发送请求信息的客户端对应的channel对象

创建byteBuffer 来处理客户端发送过来的请求信息

读取客户端发送过来的请求信息:

现在是一个客户端将请求信息写入到了readBuffer中, 我们需要向其它所有连接的客户端发送信息

 现在我们进行一个写操作:

调用byteBuffer中的flip方法进行反转:

对byteBuffer中的内容进行解码:

打印请求信息:

验证一下程序的正确性:

启动服务器

 

nc连接

程序出错了o(╥﹏╥)o

 

分析问题:

 

打印出来说明代码执行了。

再次发送,信息竟然能够发送出来

 

但是都会有空指针异常;

原因在于我们没有将当前使用过的key清除掉,导致出现空指针异常。

 

重新启动

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值