TCP协议下大数据传输IOCP乱序问题
毕业后稀里糊涂的闭门造车了两年,自己的独立博客也写了两年,各种乱七八糟,最近准备把自己博客废了,现在来看了下这两年写的对我来说略微有点意义的文章只此一篇,转载过来以作留念。
写的很肤浅且凌乱,请见谅。
我的服务器主要完成一个内网音视频实时转发功能,以及其他一些业务。设计大概如下:
服务器上分为接收线程,业务处理线程,发送线程。接收线程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乱序问题的更多相关文章
- tcp协议下的Socket
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net ...
- TCP协议传输大文件读取时候的问题
TCP协议传输大文件读取时候的问题 大文件传不完的bug 我们在定义的时候定义服务端每次文件读取大小为10240, 客户端每次接受大小为10240 我们想当然的认为客户端每次读取大小就是10240而把 ...
- TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q
TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q 一.TCP协议下的服务端并发 ''' 将不同的功能尽量拆分成不同的函数,拆分出来的功能可以被多个地方使用 TCP服务 ...
- TCP协议下Socket的基础编程类型
套接字的基本操作有: 创建(socket).命名(bind).侦听(listen).连接(accept).关闭(shutdown).发送(send).接受(recv). 下面逐个分析: 一.创建(so ...
- 基于tcp协议下粘包现象和解决方案,socketserver
一.缓冲区 每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区.write()/send() 并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送 ...
- 《java入门第一季》之tcp协议下的网络编程
tcp协议相对于udp更加安全. 首先看一下需求:服务器端开启,多个客户端同时向服务器发送数据,看哪个客户端先到达. 说明:这里我开启三个电脑实验,一台电脑写服务器端的程序,两台电脑开客户端的程序.服 ...
- 在TCP协议下的数据传送
本人小白菜逼一枚,,,,刚建立博客,也写不了太深入的,就写点上课的笔记什么的.有错误希望广大博友指出,我一定虚心学习接收改正. 我的新浪邮箱:liudaohui0805@sina.com 我的QQ邮箱 ...
- tcp协议下粘包问题的产生及解决方案
1 tcp有粘包及udp无粘包 - TCP 是面向连接的,面向流的可靠协议:发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据, 合并成 ...
- 基于TCP协议的大文件传输(粘包问题处理)
基于TCP的大文件上传服务端实现 # 服务端 # -*- coding: utf-8 -*- from socket import * import json, struct server = soc ...
随机推荐
- ACM: HDU 2544 最短路-Dijkstra算法
HDU 2544最短路 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Descrip ...
- ffmpeg入门
总入口 http://blog.csdn.net/leixiaohua1020/article/details/15811977 各结构体介绍 http://blog.csdn.net/leixiao ...
- Linux open函数
Linux open函数 open 函数用于打开和创建文件.以下是 open 函数的简单描述 #include <fcntl.h> int open(const char *pathnam ...
- 在配置IIS负载均衡时,引起的一系列问题
问题一: IIS中要上传文件的路径是另一台服务器的地址(如:本机IP是192.168.0.100,文件保存的路径在://192.168.0.101/images/folder),在上传时抛出异常: A ...
- Redis整合Spring结合使用缓存实例(三)
一.Redis介绍 什么是Redis? redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set( ...
- [LintCode] Maximal Rectangle 最大矩形
Given a 2D boolean matrix filled with False and True, find the largest rectangle containing all True ...
- android几个实用的判定代码
之前项目有几个判定代码很实用,特此做一个整理. 一.验证手机格式是否正确 //判断手机号码是否合理 private boolean judgePhoneNums(String phoneNums) { ...
- chrome 优秀的插件推荐
就本人使用过的chrome插件推荐下: 1:Adblock Plus 免费的广告拦截器,可阻止所有烦人的广告及恶意软件和跟踪. 2:ChaZD 英文翻译,妈妈再也不用担心我英文看不懂了,ChaZD 查 ...
- A+B Problem III-(涉及误差)NYOJ-477
描述求A+B是否与C相等. 输入 T组测试数据. 每组数据中有三个实数A,B,C(-10000.0<=A,B<=10000.0,-20000.0<=C<=20000.0) ...
- 使用ImageCreate()创建一个代表空白图像的变量
在建立图像创建环境之前,还需要做一些准备工作.首先,安装t1lib接着安装jpeg-6b,然后再安装GD库文件.在安装时一定要按这里给定的顺序进行安装,因为在编译GD入库时会用到jpeg-6b,如果没 ...