实现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. 第1节 flume:15、flume案例二,通过自定义拦截器实现数据的脱敏

    1.7.flume案例二 案例需求: 在数据采集之后,通过flume的拦截器,实现不需要的数据过滤掉,并将指定的第一个字段进行加密,加密之后再往hdfs上面保存 原始数据与处理之后的数据对比 图一  ...

  2. c语言产生随机数的方法

    在C语言中,rand()函数可以用来产生随机数,但是这不是真真意义上的随机数,是一个伪随机数,是根据一个数,我们可以称它为种子,为基准以某个递推公式推算出来的一系数,当这系列数很大的时候,就符合正态公 ...

  3. 获取 request 中 json 数据

    import java.io.IOException; import javax.servlet.http.HttpServletRequest; /** * request 对象的相关操作 * @a ...

  4. java在线聊天项目 使用SWT快速制作登录窗口,可视化窗口Design 更换窗口默认皮肤(切换Swing自带的几种皮肤如矩形带圆角)

    SWT成功激活后 new一个JDialog 调整到Design视图 默认的视图模式是BorderLayout,无论你怎么拖拽,只能放到东西南北中的位置上 所以,我们把视图模式调整为AbsoluteLa ...

  5. APIO2019&&THUSC2019游记

    APIO2019懵十三记: day0: 早上和ljx从沈阳出发,下午一点到的首师大附. 由于工作人员中午十二点就散了,我们就先去试机了. 下午三点接到狗牌和T恤,晚上买麦当劳回如意吃. 晚上还有场模拟 ...

  6. 【dp】淘宝的推荐系统

    可能最近做二分和DFS做傻了? 小明刚刚入职淘宝,老大给他交代了一个简单的任务,实现一个简易的商品推荐系统. 这个商品推荐系统的需求如下: 一共有 n 件商品可以被推荐,他们的编号分别为 1 到 n. ...

  7. (55)zabbix模板嵌套

    在zabbix使用过程中,在某些情况下,一个host需要link多个模板.这么做显得比较麻烦,很容易忘记到底要link哪些模板,我想link一个模板就达成这个目标,行不行?然没问题,zabbix模板内 ...

  8. C/SV/VERILOG语句块界定符不一样

    C是一对大括号{} SV /VERILOG 是begin...end

  9. centos 装 android studio (2)

    这里,我打算安装 JDK 1.8. $ sudo add-apt-repository ppa:webupd8team/java $ sudoapt-get update $ sudoapt-get ...

  10. loj2145 「SHOI2017」分手是祝愿

    记 \(f_i\) 是从要做 \(i\) 步好操作变成要做 \(i-1\) 步好操作的期望操作次数. 显然 \(f_i=i/n \times 1 + (1-i/n) \times (1 + f_{i+ ...