采纳答案成功!
向帮助你的同学说点啥吧!感谢那些助人为乐的人
第一:这里一直读不需要考虑rBuffer的size太小而读不下的情况么?
第二:client.read() 一次能读多少数据?rBuffer的大小?
同学你好~
每一次调用SocketChannel的read方法向buffer里面写数据时,最多只会从channel中读取buffer目前还可以存储的数据长度(注意,如果此时buffer中已经有数据的话,这个可存储长度是会小于buffer总长度的)。
所以如果channel中可读的数据长度超出了目前buffer的容量,那么while循环中继续调用read方法所返回的值就是0,于是while循环跳出。可是,这里返回0,并不是因为此时channel中没有数据可读,而是因为buffer已经满了。
但是,不要忘记,这时channel中还有可读的数据没读完呢。那么我们再一次调用selector的select方法时,会又一次收到这个channel的READ事件,于是我们客户端就会继续的读取channel中还没被读完的数据。
那如果第一次read返回0(buffer满),部分数据滞留在channel中,会不会导致第一次read到的数据在打印时乱码?或者是错误? 比如最后一个中文是三个字节,buffer的1024位放置的是该字符的第一个字节,那么这时候第一次读到的位置就是1024,打印时会不会乱码?
非常正确~你只要将我们代码中使用的默认buffer尺寸改到小于一个字符的长度,就可以观察到你说的情况(即打印出乱码)。一般来说,解决方案是定义我们这个聊天室应用自己的协议(参考课程一开始讲解的应用层协议)。在这个自定义协议中,我们可以在消息的抬头(header)中,写入完整消息的长度。这样一来,我们在使用buffer读取数据的时候,就可以判断一下我们读取的是否为完整的消息,然后决定是继续读取数据,还是开始处理/显示已经读取的完整数据了。这一部分的处理,主要涉及通信协议的设计,而和IO模型的关系不太密切,所以我暂时没有把这部分实现加在代码中,担心干扰了大家对于IO模型的学习。在后续升级中,我可以把这一部分代码实现也添加进去~ 当然了,如果有同学愿意自己来实现一下,欢迎大家把代码用pull request推到仓库中,我一定仔细帮大家review~
多谢老师,没做过这块,所以思路没打开。
登录后可查看更多问答,登录/注册
对比式学习助你真正理解BIO/NIO/AIO三大网络编程模型。
1.4k 1
856 5
862 5
832 5
863 5