首页 > 编程知识 正文

tcpudp测试工具手机版,测试网卡带宽的工具

时间:2023-05-06 21:10:43 阅读:227485 作者:3469

源码可以从幸福的鲜花的github上下载到,位置在muduo-masterexamplesacettcp

TTCP是一个传统的测试TCP性能的工具,它主要测试两个机器之间TCP的吞吐量,在应用层模拟消息传递的过程——客户端发送一个包,服务端对包进行确认,并且在确认之前客户端不发送下一个包。可以设置发包的数量和每个包的大小,程序计算传输所有包所用的时间,然后计算出带宽。

操作流程图

以上发送的message都是在应用层中体现的。当一个client发起ttcp的请求时,首先会向server发送一个SessionMessage,里边主要包含了即将发送的数据包个数和每个包的长度。PayloadMessage便是实际的数据,里边包含了一个表示长度的length,和实际的数据data,其中data使用了柔性数组。

main.cc

#include <examples/ace/ttcp/common.h>#include <assert.h>int main(int argc, char* argv[]){ Options options;//用来保存输入的参数信息 if (parseCommandLine(argc, argv, &options))//把命令行输入的参数保存到结构体中 { if (options.transmit)//让发送端和接收端分别执行对应的函数 { transmit(options); } else if (options.receive) { receive(options); } else { assert(0); } }}

common.h

#pragma once#include <string>#include <stdint.h>struct Options{ uint16_t port;//端口 int length;//报文长度 int number;//报文数量 bool transmit, receive, nodelay;//发送端,接收端,是否在传输层禁用negla算法 std::string host;//主机名 Options() : port(0), length(0), number(0), transmit(false), receive(false), nodelay(false) { }};bool parseCommandLine(int argc, char* argv[], Options* opt);//解析命令struct sockaddr_in resolveOrDie(const char* host, uint16_t port);//通过域名和端口解析出服务端的sockaddrstruct SessionMessage//本次请求的信息{ int32_t number;//报文数量 int32_t length;//报文长度} __attribute__ ((__packed__));struct PayloadMessage//消息报文{ int32_t length;//长度 char data[0];//数据};void transmit(const Options& opt);//发送端void receive(const Options& opt);//接收端

ttcp_blocking.cc

#include <examples/ace/ttcp/common.h>#include <muduo/base/Timestamp.h>#include <muduo/base/Types.h>#undef NDEBUG#include <assert.h>#include <errno.h>#include <stdio.h>#include <unistd.h>#include <netinet/in.h>#include <arpa/inet.h>static int acceptOrDie(uint16_t port)//一次只服务一个客户端,创建一个listenfd收到连接就close,返回clientsock{ int listenfd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); assert(listenfd >= 0); int yes = 1; if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) { perror("setsockopt"); exit(1); } struct sockaddr_in addr; muduo::memZero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = INADDR_ANY; if (bind(listenfd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) { perror("bind"); exit(1); } if (listen(listenfd, 5)) { perror("listen"); exit(1); } struct sockaddr_in peer_addr; muduo::memZero(&peer_addr, sizeof(peer_addr)); socklen_t addrlen = 0; int sockfd = ::accept(listenfd, reinterpret_cast<struct sockaddr*>(&peer_addr), &addrlen); if (sockfd < 0) { perror("accept"); exit(1); } ::close(listenfd); return sockfd;}static int write_n(int sockfd, const void* buf, int length)//写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;}static int read_n(int sockfd, void* buf, int length)//读legnth个字符,返回读到的字符个数{ 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;}void transmit(const Options& opt)//发送端执行{ struct sockaddr_in addr = resolveOrDie(opt.host.c_str(), opt.port);//输入域名端口,返回表示server的sockaddr printf("connecting to %s:%dn", inet_ntoa(addr.sin_addr), opt.port); int sockfd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); assert(sockfd >= 0); int ret = ::connect(sockfd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr));//连接服务端 if (ret) { perror("connect"); printf("Unable to connect %sn", opt.host.c_str()); ::close(sockfd); return; } printf("connectedn"); muduo::Timestamp start(muduo::Timestamp::now());//记录当前时间 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]; } double total_mb = 1.0 * opt.length * opt.number / 1024 / 1024;//计算大小 printf("%.3f MiB in totaln", total_mb); 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); } ::free(payload); ::close(sockfd); double elapsed = timeDifference(muduo::Timestamp::now(), start);//输出结果 printf("%.3f secondsn%.3f MiB/sn", elapsed, total_mb / elapsed);}void receive(const Options& opt){ int sockfd = acceptOrDie(opt.port);//接受客户端连接 struct SessionMessage sessionMessage = { 0, 0 }; if (read_n(sockfd, &sessionMessage, sizeof(sessionMessage)) != sizeof(sessionMessage))//读消息报文 { perror("read SessionMessage"); exit(1); } sessionMessage.number = ntohl(sessionMessage.number); sessionMessage.length = ntohl(sessionMessage.length); printf("receive number = %dnreceive length = %dn", sessionMessage.number, sessionMessage.length); const int total_len = static_cast<int>(sizeof(int32_t) + sessionMessage.length); PayloadMessage* payload = static_cast<PayloadMessage*>(::malloc(total_len));//申请对应大小的缓冲区 assert(payload); for (int i = 0; i < sessionMessage.number; ++i)//读数据发ack { 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); } } ::free(payload); ::close(sockfd);}

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。