TeamTalk源码分析(2)

一、接收后解包 

将这个流程抽象出来,这个流程也是现在所有网络通信库都要做的工作:

 1 while(退出条件)  
 2 {  
 3    //1. 检测非侦听socket可读  
 4    //2. 处理可读事件  
 5    //3. 检测可读取的字节数,出错就关闭,不出错,将收取的字节放入连接的读缓冲区  
 6    //循环做以下处理  
 7    //4. 检测可读缓冲区数据大小是否大于等于一个包头大小: 否,数据不够一个包,跳出该循环;  
 8    //    是,从包头中得到一个包体的大小,检测读缓冲区是否够一个包头+包体的大小;否,数据不够一个包,跳出循环  
 9    //    是,解包,根据包命令号,处理该包数据,可以产生一个任务,丢入任务队列。  
10    //    从可读缓冲区中移除刚才处理的包数据的字节数目。  
11    //    继续第4步。  
12 }  

之后将具体的业务逻辑放入任务队列。当加入任务后,任务队列线程被唤醒,从任务队列的头部拿出该任务执行。


二、封包后发送

总结下应答数据包的流程:

1 //1. 主消息泵检测到有其他任务需要做,做之。  
2 //2. 该任务是从全局的链表中取出应答包数据,找到对应的连接对象,然后尝试直接发出去;  
3 //3. 如果发不出,则将该数据存入该连接的发送缓冲区(写缓冲区),并监听该连接的socket可写事件。  
4 //4. 下次该socket触发可写事件时,接着发送该连接的写缓冲区中剩余的数据。如此循环直到所有数据都发送成功。  
5 //5. 取消监听该socket可写事件,以避免无数据的情况下触发写事件(该事件大多数情况下很频繁)  

执行步骤1之前业务逻辑已将应答数据包封好放入全局变量 s_response_pdu_list。

步骤 1 执行:主线程事件循环。s_response_pdu_list 不为空则执行发送应答数据包业务,即回调 proxy_loop_callback 。

步骤 2 执行: void proxy_loop_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam),从全局变量 s_response_pdu_list 取出应答数据包,找出对应的连接 CProxyConn  pConn;然后调用 CProxyConn::SendPdu(ResponsePdu_t*) “发出去”。但是,还是不行,因为这还没有解决上文提出的该连接上对端的tcp窗口太小导致数据发不出的问题。所以 pConn->SendPdu() 方法中一定不是调用底层函数 send(2) 直接发送数据。

步骤 3 执行:先试着调用底层send(2)方法去发送应答数据包,能发多少是多少,剩下发不完的,写入该连接的发送缓冲区中,并将忙碌标志 m_busy 置位(设置为ture),并监听可写事件。反之,如果数据一次性发送完成,则调用数据发送完成函数 OnWriteComplete(),这个函数目前为空,即不做任何事情。

步骤 4 执行:当该连接发生可写事件后,判断忙碌标志,若不忙碌则接着发送该连接的写缓冲区中剩余的数据,否则继续监听可写事件。如此循环直到所有数据都发送成功。

步骤 5 执行:整个应答数据包全部发送完后,记得移除该连接的可写事件

上面的流程从第2步到第5步也是主流网络库的发数据的逻辑。总而言之,就是说,先试着发送数据,如果发不出去,存起来,监听可写事件,下次触发可写事件后接着发。一直到数据全部发出去后,移除监听可写事件。通常只要可写事件是不断会触发的,所以默认不监听可写事件,只有数据发不出的时候才会监听可写事件。这个原则,千万要记住。(redis的网络通信模块也是如此操作

原因:

非阻塞套接字模式下,如果由于对端tcp窗口太小(导致tcp窗口太小的常见原因是:对方无法收包或不及时收包,数据积压在对方网络协议栈里面),不足以将数据发出去,它将立刻返回,不会阻塞执行流,此时返回值为-1,错误码是EAGAIN或EWOULDBLOCK,表示当前数据发不出去,希望你下次再试。但是返回值如果是-1,也可能是真正的出错了,也可能得到错误码EINTR,表示被linux信号中断了,这点需要注意一下。recv函数与send函数情形一样。


参考资料

(四)服务器端db_proxy_server源码分析4

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值