1、ttcp作用:检测TCP吞吐量
2、ttcp协议:
3、一次写一定长度的数据
static int write_n(int sockfd, const void* buf, int length)
{
int written = 0;
while (written < length)
{
ssize_t nw = ::write(sockfd, static_cast<const char*>(buf) + written, length - written);
if (nw > 0)
{
written += static_cast<int>(nw);
}
else if (nw == 0)
{
break; // EOF
}
else if (errno != EINTR)
{
perror("write");
break;
}
}
return written;
}
4、一次读一定长度的数据
static int read_n(int sockfd, void* buf, int length)
{
int nread = 0;
while (nread < length)
{
ssize_t nr = ::read(sockfd, static_cast<char*>(buf) + nread, length - nread);
if (nr > 0)
{
nread += static_cast<int>(nr);
}
else if (nr == 0)
{
break; // EOF
}
else if (errno != EINTR)
{
perror("read");
break;
}
}
return nread;
}
5、协议实现过程
//发送端
//先发送SessionMessage,确定发送数据的包数,以及每包大小
struct SessionMessage sessionMessage = { 0, 0 };
sessionMessage.number = htonl(opt.number);
sessionMessage.length = htonl(opt.length);
if (write_n(sockfd, &sessionMessage, sizeof(sessionMessage)) != sizeof(sessionMessage))
{
perror("write SessionMessage");
exit(1);
}
//生成测试数据
const int total_len = static_cast<int>(sizeof(int32_t) + opt.length);
PayloadMessage* payload = static_cast<PayloadMessage*>(::malloc(total_len));
assert(payload);
payload->length = htonl(opt.length);
for (int i = 0; i < opt.length; ++i)
{
payload->data[i] = "0123456789ABCDEF"[i % 16];
}
//发送数据
for (int i = 0; i < opt.number; ++i)
{
int nw = write_n(sockfd, payload, total_len);
assert(nw == total_len);
int ack = 0;
int nr = read_n(sockfd, &ack, sizeof(ack));//数据发送完,等待服务端回复接收数据的长度
assert(nr == sizeof(ack));
ack = ntohl(ack);
assert(ack == opt.length);//判断数据长度是否满足
}
double elapsed = timeDifference(muduo::Timestamp::now(), start);
printf("%.3f seconds\n%.3f MiB/s\n", elapsed, total_mb / elapsed);
//最后记录时间差,计算出吞吐量
//接收端---和客户端一样
//接收SessionMessage
struct SessionMessage sessionMessage = { 0, 0 };
if (read_n(sockfd, &sessionMessage, sizeof(sessionMessage)) != sizeof(sessionMessage))
{
perror("read SessionMessage");
exit(1);
}
//接收每一包
for (int i = 0; i < sessionMessage.number; ++i)
{
payload->length = 0;
if (read_n(sockfd, &payload->length, sizeof(payload->length)) != sizeof(payload->length))
{
perror("read length");
exit(1);
}
payload->length = ntohl(payload->length);
assert(payload->length == sessionMessage.length);
if (read_n(sockfd, payload->data, payload->length) != payload->length)
{
perror("read payload data");
exit(1);
}
int32_t ack = htonl(payload->length);//数据包长度
if (write_n(sockfd, &ack, sizeof(ack)) != sizeof(ack))//应答回复接收到的数据包长度
{
perror("write ack");
exit(1);
}
}