日期:2014-05-16  浏览次数:20700 次

TCP接受数据问题?当一次到达的数据长度大于接受设置的最大长度时怎么办?
我的TCP服务器接受数据长度最大设置1500 接受的buffer也是1500 但是当来的网络上来的数据大于1500(也就是recv返回的长度是1500)的时候 我发现数据有丢失 这是什么原因了?
 
当我都设置成15000数据才没有丢失 因为这个时候没有一次性来的数据是超过15000的

还有即使我把接受数据的buffer设置的很大比如15000,接受最大长度还是1500 依然当网络上来的数据大于1500的时候会发现有数据丢失,
 
总之:我发现只要一次性来的数据大于最大长度就会 有丢失数据的情况

求各位大神解答疑惑 感激不尽!


------解决方案--------------------
问题应该在接收端。用epoll要注意ET和LT。
------解决方案--------------------
哦,,对对,有这种可能就是:你用的epoll是工作有ET模式下,而你又的传进去的buffer不够大的时候,一次读不完,即状态不改变,然后下次用epoll_wait时就一直等不到通知了。

LZ看看你是否用的epoll的ET模式。
探讨

问题应该在接收端。用epoll要注意ET和LT。

------解决方案--------------------
数据不要轻易走pipe, 用pipe来做事件通知, 将待处理的数据包放在内存队列里, I/O线程也不用同步的等, 将待处理包丢给处理线程, 自己注册个write事件就可以继续干别的事了, 等处理线程处理完了把结果丢到队列里, 往I/O线程的pipe丢1字节就行了, I/O线程可以将结果对应的client的状态改为已完成, 等client的write事件再次触发就可以检测到已完成, 就可以继续往下干事了, 整个过程一定是可异步的.

实际优秀的设计是需要状态机这种简单的机制来帮助程序员解脱的, 而且绝大多数服务端也就是这么实现的, 一个client将会经历一系列的状态, 在一个状态逗留等待异步处理是完全可行的, 并且是不需要阻塞其他client的, 只要你保证给这个client一个等待超时检测或者你保证异步处理一定会有结果事件触发client.

lighttpd/nginx的设计就是一个典型的一应一答的协议, 但这不意味着就要阻塞等, 在接受到http请求后, 接下来注册write事件开始应答, 在write事件触发后遍历所有callback module, 比如第一个module是vhost Module, 它会根据请求的port/host选择一个正确的文档根目录, 这个操作会立即成功, 于是继续下一个module的回调, 结果这一步是PHP CGI吧, 于是fork+pipe+dup2, 一套完事了, 注册监听pipe, 然后这个回调没有立即结束, 于是这次write事件结束. 之后就php cgi module在event loop里从pipe读数据放到client的output buffer里. 当然, client的write事件继续触发, 一方面将output buffer实际写出, 另一方面会继续回调php cgi module询问该module是否结束以便继续回调下一个module, 这就是client处于一个应答状态, 并且卡在php cgi上, 直到某一个pipe读完了, pipe的event callback会设置对应client的php cgi module的module data中的状态位为完成, 下一次client write事件触发回调php cgi module callback时, php cgi module就放行了. 就是这么一个过程. 不需要阻塞什么.