实现TTCP (检测TCP吞吐量)

应用层协议

为了解决TCP粘包问题以及客户端阻塞问题

设计的应用层协议如下:

//告知要发送的数据包个数和长度
struct SessionMessage
{
int32_t number;
int32_t length;
} __attribute__ ((__packed__)); //数据包
struct PayloadMessage
{
int32_t length;
char data[0];//使用char[0]来表示不定长的数据,可以考虑用const char* 和 std::unique_ptr代替
};

为什么要设计应用层ACK?

因为我们测量的是应用层的流量,只有这样才能保证测出的流量是有应用层收到的而不是传输层收到的,具体一点说,TCP 的 ACK 表示对方的协议栈已经收到了你发的数据,不代表对方的应用程序收到了你发的消息。

测试指标

带宽 Mb/s

测试程序的性能指标: 传输带宽,QPS/TPS, 以及 CPU利用率,延迟等等。

程序代码

我们主要关注业务逻辑,客户端和服务端的主要代码如下

客户端

void transmit(const Options& opt)
{
InetAddress addr(opt.port);
if (!InetAddress::resolve(opt.host.c_str(), &addr))
{
printf("Unable to resolve %s\n", opt.host.c_str());
return;
} printf("connecting to %s\n", addr.toIpPort().c_str());
TcpStreamPtr stream(TcpStream::connect(addr));
if (!stream)
{
printf("Unable to connect %s\n", addr.toIpPort().c_str());
perror("");
return;
} if (opt.nodelay)
{
stream->setTcpNoDelay(true);
}
printf("connected\n");
double start = now();
struct SessionMessage sessionMessage = { 0, 0 };
sessionMessage.number = htonl(opt.number);
sessionMessage.length = htonl(opt.length);
if (stream->sendAll(&sessionMessage, sizeof(sessionMessage)) != sizeof(sessionMessage))
{
perror("write SessionMessage");
return;
} const int total_len = sizeof(int32_t) + opt.length;
PayloadMessage* payload = static_cast<PayloadMessage*>(::malloc(total_len));
std::unique_ptr<PayloadMessage, void (*)(void*)> freeIt(payload, ::free);
assert(payload);
payload->length = htonl(opt.length);
for (int i = 0; i < opt.length; ++i)
{
payload->data[i] = "0123456789ABCDEF"[i % 16];
} double total_mb = 1.0 * opt.length * opt.number / 1024 / 1024;
printf("%.3f MiB in total\n", total_mb); for (int i = 0; i < opt.number; ++i)
{
int nw = stream->sendAll(payload, total_len);
assert(nw == total_len); int ack = 0;
int nr = stream->receiveAll(&ack, sizeof(ack));
assert(nr == sizeof(ack));
ack = ntohl(ack);
assert(ack == opt.length);
} double elapsed = now() - start;
printf("%.3f seconds\n%.3f MiB/s\n", elapsed, total_mb / elapsed);
}

服务端

void receive(const Options& opt)
{
Acceptor acceptor(InetAddress(opt.port));
TcpStreamPtr stream(acceptor.accept());
if (!stream)
{
return;
}
struct SessionMessage sessionMessage = { 0, 0 };
if (stream->receiveAll(&sessionMessage, sizeof(sessionMessage)) != sizeof(sessionMessage))
{
perror("read SessionMessage");
return;
} sessionMessage.number = ntohl(sessionMessage.number);
sessionMessage.length = ntohl(sessionMessage.length);
printf("receive buffer length = %d\nreceive number of buffers = %d\n",
sessionMessage.length, sessionMessage.number);
double total_mb = 1.0 * sessionMessage.number * sessionMessage.length / 1024 / 1024;
printf("%.3f MiB in total\n", total_mb); const int total_len = sizeof(int32_t) + sessionMessage.length;
PayloadMessage* payload = static_cast<PayloadMessage*>(::malloc(total_len));
std::unique_ptr<PayloadMessage, void (*)(void*)> freeIt(payload, ::free);
assert(payload); double start = now();
for (int i = 0; i < sessionMessage.number; ++i)
{
payload->length = 0;
if (stream->receiveAll(&payload->length, sizeof(payload->length)) != sizeof(payload->length))
{
perror("read length");
return;
}
payload->length = ntohl(payload->length);
assert(payload->length == sessionMessage.length);
if (stream->receiveAll(payload->data, payload->length) != payload->length)
{
perror("read payload data");
return;
}
int32_t ack = htonl(payload->length);
if (stream->sendAll(&ack, sizeof(ack)) != sizeof(ack))
{
perror("write ack");
return;
}
}
double elapsed = now() - start;
printf("%.3f seconds\n%.3f MiB/s\n", elapsed, total_mb / elapsed);
}

实现TTCP (检测TCP吞吐量)的更多相关文章

  1. 怎样检测TCP/UDP端口的连通性

    1 TCP端口的连通性 TC端口的连通性,一般通过telnet检测: TCP协议是面向连接的,可以直接通过telnet命令连接 telnet host-ip port 2 UDP端口的连通性 因为公司 ...

  2. TCP连接异常断开检测(转)

    TCP是一种面向连接的协议,连接的建立和断开需要通过收发相应的分节来实现.某些时候,由于网络的故障或是一方主机的突然崩溃而另一方无法检测到,以致始终保持着不存在的连接.下面介绍一种方法来检测这种异常断 ...

  3. (转)TCP连接异常断开检测

    TCP是一种面向连接的协议,连接的建立和断开需要通过收发相应的分节来实现.某些时候,由于网络的故障或是一方主机的突然崩溃而另一方无法检测到,以致始终保持着不存在的连接.下面介绍一种方法来检测这种异常断 ...

  4. TCP系列37—Keep Alive—1、TCP存活检测

    一.TCP存活(keepalive)检测的背景 对于TCP设计来说,如果一个客户端和服务器端建立连接后,不在进行数据传输,那么这个连接将会一直存在下去,理论上即使中间的路由器崩溃重启.或者中间的网络线 ...

  5. 心跳机制tcp keepalive的讨论、应用及“断网”、"断电"检测的C代码实现(Windows环境下)

    版权声明:本文为博主原创文章,转载时请务必注明本文地址, 禁止用于任何商业用途, 否则会用法律维权. https://blog.csdn.net/stpeace/article/details/441 ...

  6. High Performance Browser Networking - TCP UDP TLS

    延迟 定义和标准延迟 延迟简单地说,它是一种转移或信息包从起点到终点,所花费的时间. 延迟=发送延迟+传播延迟+处理延迟+排队延迟: Propagation delay 传播时延 传播时延这个概念.是 ...

  7. TCP协议原理与格式初探

    目录 可靠数据传输原理 停等传输下的情况 1.经过完全可靠信道的可靠数据传输 2.经具有比特差错信道的可靠数据传输 3.经具有比特差错的丢包信道的可靠数据传输 流水线传输 1.回退N步(Go-Back ...

  8. TCP拥塞控制详解

    1. 拥塞原因与代价 拥塞的代价 当分组的到达速率接近链路容量时,分组经历巨大的排队时延. 发送方必须执行重传以补偿因为缓存溢出而丢弃的分组. 发送方在遇到大时延时进行的不必要重传会引起路由器利用其链 ...

  9. 通过PowerShell获取TCP响应(类Telnet)

    通常情况下,为了检测指定的TCP端口是否存活,我们都是通过telnet指定的端口看是否有响应来确定,然而默认情况下win8以后的系统默认是不安装telnet的.设想一下如果你黑进了一个服务器,上面没装 ...

随机推荐

  1. WebStorm换主题(护眼)

    一.下载喜欢颜色的主题 http://www.phpstorm-themes.com/ 我用的豆沙绿护眼 <scheme name="Solarized Light My" ...

  2. House of Spirit(fastbin)

    0x01 fastbin fastbin所包含chunk的大小为16 Bytes, 24 Bytes, 32 Bytes, … , 80 Bytes.当分配一块较小的内存(mem<=64 Byt ...

  3. Noip2016 提高组 蚯蚓

    刚看到这道题:这题直接用堆+模拟不就可以了(并没有认真算时间复杂度) 于是用priority_queue水到了85分-- (STL大法好) 天真的我还以为是常数问题,于是疯狂卡常--(我是ZZ) 直到 ...

  4. jQuery-AJAX简介

    AJAX是浏览器后台与服务器交换数据的技术,无须加载整个页面的情况下,对页面中的局部进行更新. AJAX=异步的JavaScript与XML(Asynchronous JavaScript and X ...

  5. 解读tensorflow之rnn【转】

    转自:https://blog.csdn.net/mydear_11000/article/details/52414342 from: http://lan2720.github.io/2016/0 ...

  6. Git学习——创建本地仓库、提交文件

    创建Git仓库 新建或找一个存在的文件夹,在命令行进入该文件夹,输入命令 git init 添加文件到Git仓库 首先使用命令git add <file>,可以多次添加文件: 使用命令gi ...

  7. linux中的硬盘及flash操作

    磁盘操作是块设备的必备操作,需要认真掌握. 一.硬盘 1.硬盘文件 默认串口硬盘的设备文件为sda(第一块硬盘).sdb(第二块硬盘).... 默认并口硬盘的设备文件为hda(第一块硬盘).hdb(第 ...

  8. 《零基础入门学习Python》【第一版】视频课后答案第003讲

    测试题答案: 0. 以下哪个变量的命名不正确?为什么? (A) MM_520 (B) _MM520_ (C) 520_MM (D) _520_MM(C)选项不正确,因为 Python 中的变量名不能以 ...

  9. Hive元数据启动失败

    Caused by: java.net.ConnectException: Connection refused (Connection refused) at java.net.PlainSocke ...

  10. Disqus 升级到3.0以上版本的评论同步问题

    Disqus从2.*升级3.*时,Knowlege Base的文章不显示Disqus评论, 解决方法:在Disqus的Advanced Settings中勾选Render Comments JavaS ...