请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

while(client.read(rBuffer) > 0);

第一:这里一直读不需要考虑rBuffer的size太小而读不下的情况么?

第二:client.read() 一次能读多少数据?rBuffer的大小?

正在回答 回答被采纳积分+3

1回答

Stannum 2019-09-17 01:39:30

同学你好~

每一次调用SocketChannel的read方法向buffer里面写数据时,最多只会从channel中读取buffer目前还可以存储的数据长度(注意,如果此时buffer中已经有数据的话,这个可存储长度是会小于buffer总长度的)。

所以如果channel中可读的数据长度超出了目前buffer的容量,那么while循环中继续调用read方法所返回的值就是0,于是while循环跳出。可是,这里返回0,并不是因为此时channel中没有数据可读,而是因为buffer已经满了。

但是,不要忘记,这时channel中还有可读的数据没读完呢。那么我们再一次调用selector的select方法时,会又一次收到这个channel的READ事件,于是我们客户端就会继续的读取channel中还没被读完的数据。

0 回复 有任何疑惑可以回复我~
  • 提问者 EverL #1
    那如果第一次read返回0(buffer满),部分数据滞留在channel中,会不会导致第一次read到的数据在打印时乱码?或者是错误?
    
    比如最后一个中文是三个字节,buffer的1024位放置的是该字符的第一个字节,那么这时候第一次读到的位置就是1024,打印时会不会乱码?
    回复 有任何疑惑可以回复我~ 2019-09-17 09:52:33
  • Stannum 回复 提问者 EverL #2
    非常正确~你只要将我们代码中使用的默认buffer尺寸改到小于一个字符的长度,就可以观察到你说的情况(即打印出乱码)。一般来说,解决方案是定义我们这个聊天室应用自己的协议(参考课程一开始讲解的应用层协议)。在这个自定义协议中,我们可以在消息的抬头(header)中,写入完整消息的长度。这样一来,我们在使用buffer读取数据的时候,就可以判断一下我们读取的是否为完整的消息,然后决定是继续读取数据,还是开始处理/显示已经读取的完整数据了。这一部分的处理,主要涉及通信协议的设计,而和IO模型的关系不太密切,所以我暂时没有把这部分实现加在代码中,担心干扰了大家对于IO模型的学习。在后续升级中,我可以把这一部分代码实现也添加进去~
    当然了,如果有同学愿意自己来实现一下,欢迎大家把代码用pull request推到仓库中,我一定仔细帮大家review~
    回复 有任何疑惑可以回复我~ 2019-09-22 23:23:35
  • 提问者 EverL 回复 Stannum #3
    多谢老师,没做过这块,所以思路没打开。
    回复 有任何疑惑可以回复我~ 2019-09-23 09:15:33
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信