使用 C/C++ Socket 模拟网络条件

我正在寻找一种将网络仿真添加到套接字的方法.

I'm looking for a way to add network emulation to a socket.

基本的解决方案是为连接增加带宽限制.

The basic solution would be some way to add bandwidth limitation to a connection.

对我来说理想的解决方案是:

The ideal solution for me would:

  • 支持高级网络属性(延迟、丢包)
  • 开源
  • 具有与标准套接字类似的 API(或环绕它们)
  • 在 Windows 和 Linux 上工作
  • 支持 IPv4 和 IPv6

我看到了一些在系统级别上工作的选项,甚至作为代理(Dummynet、WANem、neten 等),但这对我不起作用,因为我希望能够手动模拟每个套接字(例如,打开一个带有调制解调器仿真的套接字和一个带有3G仿真的套接字.基本上我想知道这些工具是如何做到的.

I saw a few options that work on the system level, or even as proxy (Dummynet, WANem, neten, etc.), but that won't work for me, because I want to be able to emulate each socket manually (for example, open one socket with modem emulation and one with 3G emulation. Basically I want to know how these tools do it.

我需要将此功能嵌入到我自己的产品中,因此使用额外的盒子或需要手动配置的第三方工具是不可接受的.我想编写与那些工具做同样事情的代码,我的问题是如何去做.

I need to embed this functionality in my own product, therefore using an extra box or a third-party tool that needs manual configuration is not acceptable. I want to write code that does the same thing as those tools do, and my question is how to do it.

结语:事后看来,我的问题有点误导.显然,没有办法直接在套接字上做我想做的事.有两种选择:

Epilogue: In hindsight, my question was a bit misleading. Apparently, there is no way to do what I wanted directly on the socket. There are two options:

为发送/接收操作添加延迟(基于@PaulCoccoli 的回答):
通过在发送和接收之前添加延迟,您可以获得非常粗略的网络模拟(延迟的恒定延迟,延迟发送,每秒发送不超过 X 字节,带宽).
保罗的回答和评论给了我很大的启发,所以我奖励了他.

Add delays to send/receive operation (Based on @PaulCoccoli's answer):
by adding a delay before sending and receiving, you can get a very crude network simulation (constant delay for latency, delay sending, as to not send more than X bytes per second, for bandwidth).
Paul's answer and comment were great inspiration for me, so I award him the bounty.

将网络模拟逻辑添加为代理(基于@m0she 和其他人的回答):
要么通过代理发送请求,要么使用代理拦截请求,然后添加所需的模拟.但是,使用现成的解决方案而不是编写自己的代理实现更有意义 - 从我所看到的 Dummynet 可能是最好的选择(这就是webpagetest.org 所做的).其他选项在下面的答案中,我还会添加 DonsProxy
这是更好的方法,所以我接受这个答案.

Add the network simulation logic as a proxy (Based on @m0she and others answer):
Either send the request through the proxy, or use the proxy to intercept the requests, then add the desired simulation. However, it makes more sense to use a ready solution instead of writing your own proxy implementation - from what I've seen Dummynet is probably the best choice (this is what webpagetest.org does). Other options are in the answers below, I'll also add DonsProxy
This is the better way to do it, so I'm accepting this answer.

推荐答案

你可以在你的软件中编译一个代理来做这件事.它可以是完全成熟的 socks 代理的一些实现(如 this),或者可能更好,更简单的只为您的目的服务(并且不需要将您的通信与目的地和其他袜子开销作为前缀).该代码可以作为单独的进程或进程中的线程运行.

You can compile a proxy into your software that would do that. It can be some implementation of full fledged socks proxy (like this) or probably better, something simpler that would only serve your purpose (and doesn't require prefixing your communication with the destination and other socks overhead). That code could run as a separate process or a thread within your process.

向代理添加限制应该不会太难.你可以:

Adding throttling to a proxy shouldn't be too hard. You can:

  • 如果超过某些带宽限制,则延迟数据转发
  • 通过在缓冲区的读/写操作之前添加计时器来增加延迟.
  • 如果您使用基于连接的协议(如 TCP),丢弃数据包将毫无意义,但使用基于数据报的协议 (UDP) 也很容易实现.

连接创建 API 与普通的 posix/winsock 会有些不同(除非您执行一些宏或其他魔法),但其他一切(发送/接收/选择/关闭/等)都是相同的.

The connection creation API would be a bit different from normal posix/winsock (unless you do some macro or other magic), but everything else (send/recv/select/close/etc..) is the same.

相关文章