实现TTCP (检测TCP吞吐量)
实现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吞吐量)的更多相关文章
- 怎样检测TCP/UDP端口的连通性
1 TCP端口的连通性 TC端口的连通性,一般通过telnet检测: TCP协议是面向连接的,可以直接通过telnet命令连接 telnet host-ip port 2 UDP端口的连通性 因为公司 ...
- TCP连接异常断开检测(转)
TCP是一种面向连接的协议,连接的建立和断开需要通过收发相应的分节来实现.某些时候,由于网络的故障或是一方主机的突然崩溃而另一方无法检测到,以致始终保持着不存在的连接.下面介绍一种方法来检测这种异常断 ...
- (转)TCP连接异常断开检测
TCP是一种面向连接的协议,连接的建立和断开需要通过收发相应的分节来实现.某些时候,由于网络的故障或是一方主机的突然崩溃而另一方无法检测到,以致始终保持着不存在的连接.下面介绍一种方法来检测这种异常断 ...
- TCP系列37—Keep Alive—1、TCP存活检测
一.TCP存活(keepalive)检测的背景 对于TCP设计来说,如果一个客户端和服务器端建立连接后,不在进行数据传输,那么这个连接将会一直存在下去,理论上即使中间的路由器崩溃重启.或者中间的网络线 ...
- 心跳机制tcp keepalive的讨论、应用及“断网”、"断电"检测的C代码实现(Windows环境下)
版权声明:本文为博主原创文章,转载时请务必注明本文地址, 禁止用于任何商业用途, 否则会用法律维权. https://blog.csdn.net/stpeace/article/details/441 ...
- High Performance Browser Networking - TCP UDP TLS
延迟 定义和标准延迟 延迟简单地说,它是一种转移或信息包从起点到终点,所花费的时间. 延迟=发送延迟+传播延迟+处理延迟+排队延迟: Propagation delay 传播时延 传播时延这个概念.是 ...
- TCP协议原理与格式初探
目录 可靠数据传输原理 停等传输下的情况 1.经过完全可靠信道的可靠数据传输 2.经具有比特差错信道的可靠数据传输 3.经具有比特差错的丢包信道的可靠数据传输 流水线传输 1.回退N步(Go-Back ...
- TCP拥塞控制详解
1. 拥塞原因与代价 拥塞的代价 当分组的到达速率接近链路容量时,分组经历巨大的排队时延. 发送方必须执行重传以补偿因为缓存溢出而丢弃的分组. 发送方在遇到大时延时进行的不必要重传会引起路由器利用其链 ...
- 通过PowerShell获取TCP响应(类Telnet)
通常情况下,为了检测指定的TCP端口是否存活,我们都是通过telnet指定的端口看是否有响应来确定,然而默认情况下win8以后的系统默认是不安装telnet的.设想一下如果你黑进了一个服务器,上面没装 ...
随机推荐
- Codeforces Round #273 (Div. 2)-C. Table Decorations
http://codeforces.com/contest/478/problem/C C. Table Decorations time limit per test 1 second memory ...
- python之道06
1,使⽤循环打印以结果: * *** ***** ******* ********* 答案: 方法一: for i in range(10): if i % 2 == 1: print(i*'*') ...
- 【数学 裴蜀定理】bzoj2257: [Jsoi2009]瓶子和燃料
使gcd最大的trick Description jyy就一直想着尽快回地球,可惜他飞船的燃料不够了. 有一天他又去向火星人要燃料,这次火星人答应了,要jyy用飞船上的瓶子来换.jyy的飞船上共有 N ...
- C++简单年月日的功能实现
// C++年月日判断初步代码 #include <iostream> using namespace std; class Data { int year; int month; int ...
- Python从文件中读取数据
一.读取整个文件内容 在读取文件之前,我们先创建一个文本文件resource.txt作为源文件. resource.txt my name is joker, I am 18 years old, H ...
- Python9-继承1-day24(大年初一)
#面向对象编程:'''思想:角色的抽象,创建类,创建角色,面对对象的关键字class 类名: 静态属性 = ‘aaa' def __init__(self):pass 类名.静态属性 ———存储在类的 ...
- (原)pat1007素数猜想
---恢复内容开始--- 1007. 素数对猜想 (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 让我们 ...
- 【21】外边距折叠(collapsing margins)
[21]外边距折叠(collapsing margins) 外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距. 合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者. [注意]m ...
- Python标准库之csv(1)
Python标准库之csv(1) 1.Python处理csv文件之csv.writer() import csv def csv_write(path,data): with open(path,'w ...
- 4C. Stars
4C. Stars Time Limit: 2000ms Case Time Limit: 2000ms Memory Limit: 65536KB 64-bit integer IO forma ...