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 ...
随机推荐
- 优化特性(Attribute)性能
通过这篇文章,不仅可以了解到Attribute的工作原理,还可以了解到GetcustomeAttribute是的内部执行流程.最后,你会看到,使用缓存机制可以极大的优化反射Attribute的性能. ...
- fuser 命令的介绍
fuser 可以显示出当前哪个程序在使用磁盘上的某个文件.挂载点.甚至网络端口,并给出程序进程的详细信息. fuser显示使用指定文件或者文件系统的进程ID.默认情况下每个文件名后面跟一个字母表示访 ...
- C/C++:[2]enum-枚举量声明、定义和使用
C/C++:[2]enum-枚举量声明.定义和使用 转自:http://jingyan.baidu.com/article/e75aca85526c1b142edac6d9.html 众所周知,C/C ...
- ActiveMQ 即时通讯服务——浅析
一. 概述与介绍 ActiveMQ 是Apache出品,最流行的.功能强大的即时通讯和集成模式的开源服务器.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provide ...
- [zt]OpenCV2.1.0的安装
下载和安装 OpenCV 2.1.0 2.添加库文件:打开VS 2008,选择菜单:Tools->options->Projects and Solutions >VC++ Dire ...
- 8.0/9.0 Email 设置
Email 设置一直都是Odoo的一个坑,巨坑. 先讲结论,发邮件可以用,收还是算了吧 1. 发邮件设置 发的设置相对简单,如果企业邮箱支持catcll all功能,基本不用改动可以直接用,否则需要安 ...
- Daily Scrum 11.4
昨天会议结束后熬夜较晚,没有及时添加会议记录到博客上,今天补上. Member Today’task Tomorrow’task 张恿 挖掘程序潜力 根据今天的总结对程序进行改进 吴文会 明日返校.. ...
- Sql Server按树形结构排序查询表记录
http://blog.csdn.net/dxnn520/article/details/8089149 ----------------------------------------------- ...
- html - 自动播放音乐
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Web前端开发基础 第四课(认识CSS样式)
CSS代码语法 css 样式由选择符和声明组成,而声明又由属性和值组成,如下图所示: 选择符:又称选择器,指明网页中要应用样式规则的元素,如本例中是网页中所有的段(p)的文字将变成蓝色,而其他的元素( ...