用C++实现HTTP服务器 - 如何控制一个套接字的发送带宽
2011-07-15 17:20
429 查看
用C++实现HTTP服务器 - 如何控制一个套接字的发送带宽
作者: 阙荣文
日期: 2011/7/15
目的
对HTTP服务器的每一个客户套接字限制发送带宽.
前提
用IOCP管理套接字,不能阻塞线程影响到别的连接.
如何实现
思路1. 每次调用 WSASend()的时候,计算一下当前带宽,如果超出限制,那么只发送一个最小的包,比如1个字节使带宽慢慢降到合适.
优点: 简单,容易实现.
缺点:除了不能够精确的控制发送带宽外,这种方法还有另一个比较大的问题:即使每次调用WSASend()时只发送1个字节的数据,在网络条件好的情况下,发送速度依然能达到30KB/s左右(我在本机上用 Que's HTTP Server 测试的结果,仅供参考),即带宽最小只能控制在30KB/s,实际意义不大.
思路2.每次调用WSASend()的时候,如果发现速度超限,则计算出下次发送数据的时间点,然后延时发送.
假设: 已发送字节数为 BytesSent, 最大速度限制为 MaxSpeed, 套接字开始发送数据的时间为 StartTime, 那么下次发送数据包的时间 NextSendTime = BytesSent / MaxSpeed + StartTime. 每次调用 WSASend()时都查看一下当前 时间CurTime,如果 CurTime < NextSendTime, 说明速度超限, 则设置一个定时器,在 (NextSendTime - CurTime) 的时间间隔后触发,继续发送下一个包. 如果速度没有超限则正常处理.
优点: 可以精确的控制任意大小的带宽.
缺点: 需要定时器支持,消耗比较多资源,编程的时候也更复杂,要做好同步.并且如果 (NextSendTime - CurTime) 的值过长,有可能会导致客户端认为服务器没响应而断开连接,影响正常的服务.
为了克服上面的缺点,应该设置一个最长延时的值 MaxDelay, 当(NextSendTime - CurTime) > MaxDelay时,定时器超时设置为MaxDelay,并定时器触发后,只发送一个最小长度的包,以保持连接的活跃性. 以 Que's HTTP Server 为例, MaxDelay 设置为2秒, 如果延时发送的时间(NextSendTime - CurTime) 大于2秒,则设置一个定时器,在2秒后触发,发送一个长度为 512 字节(MinDataLength)的数据包. 这样,可以得出结论: Que's HTTP Server 限制带宽的理论下限为 256B/s. 作为HTTP 服务器,这个数值足够了,如果需要限制更小的带宽,可以减小MinDataLength的值,或者增大MaxDelay的值. 比如设置 MaxDelay = 5s, MinDataLength = 10 Bytes, 则最小带宽为 2 B/s.
结论
采用第二种方法,可以有效而精确的控制发送带宽,这也是 Que's HTTP Server采用的办法.
请点击查看有关Que's HTTP Server 的更多细节.
----
----
作者: 阙荣文
日期: 2011/7/15
目的
对HTTP服务器的每一个客户套接字限制发送带宽.
前提
用IOCP管理套接字,不能阻塞线程影响到别的连接.
如何实现
思路1. 每次调用 WSASend()的时候,计算一下当前带宽,如果超出限制,那么只发送一个最小的包,比如1个字节使带宽慢慢降到合适.
优点: 简单,容易实现.
缺点:除了不能够精确的控制发送带宽外,这种方法还有另一个比较大的问题:即使每次调用WSASend()时只发送1个字节的数据,在网络条件好的情况下,发送速度依然能达到30KB/s左右(我在本机上用 Que's HTTP Server 测试的结果,仅供参考),即带宽最小只能控制在30KB/s,实际意义不大.
思路2.每次调用WSASend()的时候,如果发现速度超限,则计算出下次发送数据的时间点,然后延时发送.
假设: 已发送字节数为 BytesSent, 最大速度限制为 MaxSpeed, 套接字开始发送数据的时间为 StartTime, 那么下次发送数据包的时间 NextSendTime = BytesSent / MaxSpeed + StartTime. 每次调用 WSASend()时都查看一下当前 时间CurTime,如果 CurTime < NextSendTime, 说明速度超限, 则设置一个定时器,在 (NextSendTime - CurTime) 的时间间隔后触发,继续发送下一个包. 如果速度没有超限则正常处理.
优点: 可以精确的控制任意大小的带宽.
缺点: 需要定时器支持,消耗比较多资源,编程的时候也更复杂,要做好同步.并且如果 (NextSendTime - CurTime) 的值过长,有可能会导致客户端认为服务器没响应而断开连接,影响正常的服务.
为了克服上面的缺点,应该设置一个最长延时的值 MaxDelay, 当(NextSendTime - CurTime) > MaxDelay时,定时器超时设置为MaxDelay,并定时器触发后,只发送一个最小长度的包,以保持连接的活跃性. 以 Que's HTTP Server 为例, MaxDelay 设置为2秒, 如果延时发送的时间(NextSendTime - CurTime) 大于2秒,则设置一个定时器,在2秒后触发,发送一个长度为 512 字节(MinDataLength)的数据包. 这样,可以得出结论: Que's HTTP Server 限制带宽的理论下限为 256B/s. 作为HTTP 服务器,这个数值足够了,如果需要限制更小的带宽,可以减小MinDataLength的值,或者增大MaxDelay的值. 比如设置 MaxDelay = 5s, MinDataLength = 10 Bytes, 则最小带宽为 2 B/s.
结论
采用第二种方法,可以有效而精确的控制发送带宽,这也是 Que's HTTP Server采用的办法.
请点击查看有关Que's HTTP Server 的更多细节.
----
----
相关文章推荐
- 用C++实现HTTP服务器 - 如何控制一个套接字的发送带宽
- 如何用C++实现一个LRU Cache(转载)
- 如何用C++轻松实现线程控制-1
- 如何用C++实现一个LRU Cache
- 如何用C++实现一个LRU Cache
- [转]如何用C++实现一个LRU Cache
- C++多态是如何实现的——一个简单明晰的例子告诉你!
- C++如何实现启动一个进程并把该进程的标题改为我的标题
- C++中如何用cout实现输出的填充,宽度,对齐及其精度控制
- 做一个IOS聊天APP如何实现发送/预览文件的功能
- 面试例题:输入n,求一个n x n矩阵,规定矩阵沿45度递增,形成一个zigzag数组(JPEG编码里取像素数据的排列顺序),请问如何用C++实现? (中国台湾著名硬件公司2007年11月面试题)
- 编写一个聊天程序:有接收数据部分,和发数据的部分, 这两部分需要同时执行,使用多线程实现,一个控制接收,一个控制发送
- 一个利用windows api控制放音音量和录音麦克风音量实现类(c++代码)
- c++中如何实现一个不能被继承的类
- 如何用C++轻松实现线程控制-3
- 如何用C++轻松实现线程控制-2
- 如何用C++实现一个LRU Cache
- c++ 如何用一个函数实现两个字符串的比较
- 如何使用echart的Graph图实现一个流程控制图
- 对面试题“输入n,求一个nXn矩阵,规定矩阵沿45度递增,形成一个zigzag数组(JPEG编码里取像素数据的排列顺序),请问如何用C++实现?”的理解