毕业后稀里糊涂的闭门造车了两年,自己的独立博客也写了两年,各种乱七八糟,最近准备把自己博客废了,现在来看了下这两年写的对我来说略微有点意义的文章只此一篇,转载过来以作留念。

写的很肤浅且凌乱,请见谅。

我的服务器主要完成一个内网音视频实时转发功能,以及其他一些业务。设计大概如下:

服务器上分为接收线程,业务处理线程,发送线程。接收线程socket绑定到完成端口。业务处理线程是采用多线程的模拟完成端口,发送线程也是多线程采用模拟完成端口。这样做的目的是想业务处理线程阻塞并不影响发送和接收。

客户端业务层需要发送一个数据,我视为大包数据,传输层把大包数据进行拆分,变成小包发送到服务器。服务器收齐一个大包后,加入接收队列。业务处理线程从接收队列获取大包数据,抛给业务层。服务器业务层处理后把需要转发的数据放到发送队列。发送线程从发送队列取出数据转发给需要接收数据的客户端。

此时接收客户端收到乱序,起初我怀疑是多线程传输导致的乱序。认为采用了异步传输,又多条线程发送,那么可能有的包先到有的包后到。但是!采用的TCP传输协议理论上是不会乱序的。

一、排除SEND,WSASEND导致乱序的问题

要知道如果采用的是send,TCP协议下,只要我们保证调用send是有序的,那么数据拷贝到send缓冲就是有序的,TCP协议会保证数据的顺序性到达。即便是WSASend,采用TCP原理都一样,只是WSA是非阻塞等待,它也会保证按顺序拷贝进socket的send缓冲区。所以WSASend基于TCP协议就是顺序到达的。所以,如果你的程序设计上是以小包发送为单位,发生了乱序,那一定是你设计的问题。

二、检查服务器接收数据是否乱序

这个看个人项目怎么设计了,我这里打日志是已经排除了服务器接收数据乱序的可能。

三、排除多线程发送导致的乱序

每条线发送线程从发送队列取大包数据,如果发送队列本身是顺序的,那么取出来发送这个过程就应该是顺序的。如果队列里存的是一次send能允许的最大小包,那么也应该是顺序到达(结合问题一来思考)。

四、那我的问题在哪里

答案还是多线程发送,以及多条业务处理线程。刚刚问题三虽然我否定了多线程发送导致的乱序,但是请仔细看我说的前提,是以小包为单位。

在我这个程序里,设定的是以大包为单位,大包是由小包组成的,IOCP完成端口能监控到IO完成情况,也就是小包的完成情况,但是并不能监控大包完成情况。我的各种设定只是保证了取大包这一刻是有序的。如果大包ID=1是由100个小包组成,大包ID=2是由1个小包组成,在实际发送的时候就会出现:

线程1 获取大包ID=1

线程2获取大包ID=2

线程1 发送ID=1的第一个小包

线程1 发送ID=1的第二个小包

…….线程1 发送ID=1的第n个小包

线程2发送ID=2的第1个小包

…..线程1 发送ID=1的第m个小包

客户端就先收集齐了大包ID=2的所有小包,反馈给业务层或者加入接收队列,所以业务层或者接收队列看到的数据就是乱序的。

除了发送线程,业务处理线程也是多线程,业务处理线程会把处理后的数据add到发送队列,这个add过程本身就不能保证是有序的。也就是说在send前,数据其实已经可能存在乱序了。

五、小结

如果要严格来说,TCP下IOCP本身不是导致乱序的原因,WSASend只要顺序调用也不存在乱序一说,真正导致乱序的是自己设计的问题。

题外话:

回顾这两年自己闭门造车的过程,各种尝试与猜测,哈,终究只是在浪费时间。大学一直在搞asp.net,实习搞java和android,毕业了却在做c++,哈,各种折腾到现在没有一项觉得做的深入的。从0基础开始搞c++从0开始搞传输,走了很多弯路进了很多坑,人又笨,掉进去了半天都怕不上来。。

最后这个服务器转发的传输协议坑了6个大的版本后,在第7个版本,终于经过测试能跑满千兆带宽,6核12线程的cpu消耗5%左右。不得不吐槽一下IOCP真的很厉害。

TCP协议下大数据传输IOCP乱序问题的更多相关文章

  1. tcp协议下的Socket

    import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net ...

  2. TCP协议传输大文件读取时候的问题

    TCP协议传输大文件读取时候的问题 大文件传不完的bug 我们在定义的时候定义服务端每次文件读取大小为10240, 客户端每次接受大小为10240 我们想当然的认为客户端每次读取大小就是10240而把 ...

  3. TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q

    TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q 一.TCP协议下的服务端并发 ''' 将不同的功能尽量拆分成不同的函数,拆分出来的功能可以被多个地方使用 TCP服务 ...

  4. TCP协议下Socket的基础编程类型

    套接字的基本操作有: 创建(socket).命名(bind).侦听(listen).连接(accept).关闭(shutdown).发送(send).接受(recv). 下面逐个分析: 一.创建(so ...

  5. 基于tcp协议下粘包现象和解决方案,socketserver

    一.缓冲区 每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区.write()/send() 并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送 ...

  6. 《java入门第一季》之tcp协议下的网络编程

    tcp协议相对于udp更加安全. 首先看一下需求:服务器端开启,多个客户端同时向服务器发送数据,看哪个客户端先到达. 说明:这里我开启三个电脑实验,一台电脑写服务器端的程序,两台电脑开客户端的程序.服 ...

  7. 在TCP协议下的数据传送

    本人小白菜逼一枚,,,,刚建立博客,也写不了太深入的,就写点上课的笔记什么的.有错误希望广大博友指出,我一定虚心学习接收改正. 我的新浪邮箱:liudaohui0805@sina.com 我的QQ邮箱 ...

  8. tcp协议下粘包问题的产生及解决方案

    1 tcp有粘包及udp无粘包 - TCP 是面向连接的,面向流的可靠协议:发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据, 合并成 ...

  9. 基于TCP协议的大文件传输(粘包问题处理)

    基于TCP的大文件上传服务端实现 # 服务端 # -*- coding: utf-8 -*- from socket import * import json, struct server = soc ...

随机推荐

  1. 【BZOJ】3211: 花神游历各国

    题意 \(n\)个点,第\(i\)个点值为\(a_i\).\(m\)个询问,每次询问\([l, r]\)内的和或者将\([l, r]\)的每个值改为自己的算术平方根.(\(n \le 100000, ...

  2. JavaScript基础学习篇

    1.alert消息弹出框 alert(字符串或变量); 消息对话框通常可以用于调试程序. 与document.write 相似. 2.确认:confirm消息对话框 confirm(弹出时要显示的文本 ...

  3. SpringMVC异常处理机制详解[附带源码分析]

    目录 前言 重要接口和类介绍 HandlerExceptionResolver接口 AbstractHandlerExceptionResolver抽象类 AbstractHandlerMethodE ...

  4. Go语言练习:网络编程实例——简易图片上传网站

    1.代码结构 2.运行实例 1.代码结构 $ tree . ├── photoweb.go ├── public │   ├── css │   ├── images │   └── js ├── u ...

  5. 聚合函数:sum,avg,max,min,count

    group by  分组的使用方法 数学函数:ABS.ceiling.floor.power.round.sqrt.square 练习:

  6. scala - Map基础

    Map 构造Map 不可变: val map = Map("sa" -> 1, "s" -> 2)map("sa") = 3 / ...

  7. sql2008 r2 重新启动 失败解决办法

    一.问题描述: 在计算机中安装sql_server_2008_R2,安装前执行检查时,提示重启计算机失败.重启计算机后,再执行检查仍然提示这个错误. 二.解决方案: 1.在开始->运行中输入re ...

  8. 解决HDU爆栈的问题

    转载:http://forum.byr.edu.cn/article/ACM_ICPC/51264 大家懂的,鉴于HDU用的是windows服务器,所以stack大小及其坑爹,稍微深一点的递归栈就会s ...

  9. svn学习笔记(3)设置

    1.图标集

  10. AspxSpy2014 Final

    受bin牛委托修改并发布,版权归bin牛所有. Bug/建议提交:zcgonvh@rootkit.net.cn 祝各位马年大吉,财源滚滚. 免责声明: 本程序只用于管理员安全检测,使用前请注意环境与法 ...