roundtrip_tcp.cc revision 91852b37
191852b37SShuo Chen#include "InetAddress.h" 291852b37SShuo Chen#include "TcpStream.h" 391852b37SShuo Chen 491852b37SShuo Chen#include <memory> 591852b37SShuo Chen#include <unistd.h> 691852b37SShuo Chen#include <stdlib.h> 791852b37SShuo Chen#include <stdio.h> 891852b37SShuo Chen#include <time.h> 991852b37SShuo Chen 1091852b37SShuo Chen#include <vector> 1191852b37SShuo Chen 1291852b37SShuo Chenint64_t kNanos = 1e9; 1391852b37SShuo Chenint64_t clock_diff(struct timespec x, struct timespec y) 1491852b37SShuo Chen{ 1591852b37SShuo Chen return (x.tv_sec - y.tv_sec) * kNanos + x.tv_nsec - y.tv_nsec; 1691852b37SShuo Chen} 1791852b37SShuo Chen 1891852b37SShuo Chenstruct timespec get_time() 1991852b37SShuo Chen{ 2091852b37SShuo Chen struct timespec now; 2191852b37SShuo Chen clock_gettime(CLOCK_MONOTONIC, &now); 2291852b37SShuo Chen return now; 2391852b37SShuo Chen} 2491852b37SShuo Chen 2591852b37SShuo Chenstruct Sample 2691852b37SShuo Chen{ 2791852b37SShuo Chen int index; 2891852b37SShuo Chen int64_t start_nano; 2991852b37SShuo Chen int64_t rtt_nano; 3091852b37SShuo Chen}; 3191852b37SShuo Chen 3291852b37SShuo Chenstd::vector<Sample> run(const char* host, int delay_ms, int length_s, int batch, int payload_size) 3391852b37SShuo Chen{ 3491852b37SShuo Chen struct timespec start = get_time(); 3591852b37SShuo Chen std::vector<Sample> rtts; 3691852b37SShuo Chen 3791852b37SShuo Chen InetAddress addr; 3891852b37SShuo Chen if (!InetAddress::resolve(host, 3007, &addr)) 3991852b37SShuo Chen { 4091852b37SShuo Chen printf("Unable to resolve %s\n", host); 4191852b37SShuo Chen return rtts; 4291852b37SShuo Chen } 4391852b37SShuo Chen 4491852b37SShuo Chen // printf("connecting to %s\n", addr.toIpPort().c_str()); 4591852b37SShuo Chen TcpStreamPtr stream(TcpStream::connect(addr)); 4691852b37SShuo Chen if (!stream) 4791852b37SShuo Chen { 4891852b37SShuo Chen printf("Unable to connect %s\n", addr.toIpPort().c_str()); 4991852b37SShuo Chen perror(""); 5091852b37SShuo Chen return rtts; 5191852b37SShuo Chen } 5291852b37SShuo Chen 5391852b37SShuo Chen std::unique_ptr<char[]> payload(new char[payload_size]); 5491852b37SShuo Chen 5591852b37SShuo Chen while (true) { 5691852b37SShuo Chen struct timespec now = get_time(); 5791852b37SShuo Chen if (clock_diff(now, start) > length_s * kNanos) 5891852b37SShuo Chen break; 5991852b37SShuo Chen 6091852b37SShuo Chen for (int i = 0; i < batch; ++i) { 6191852b37SShuo Chen struct timespec before = get_time(); 6291852b37SShuo Chen int nw = stream->sendAll(payload.get(), payload_size); 6391852b37SShuo Chen if (nw != payload_size) 6491852b37SShuo Chen return rtts; 6591852b37SShuo Chen int nr = stream->receiveAll(payload.get(), payload_size); 6691852b37SShuo Chen if (nr != payload_size) 6791852b37SShuo Chen return rtts; 6891852b37SShuo Chen struct timespec after = get_time(); 6991852b37SShuo Chen int64_t nanos = clock_diff(after, before); 7091852b37SShuo Chen Sample s = { 7191852b37SShuo Chen .index = i, 7291852b37SShuo Chen .rtt_nano = nanos, 7391852b37SShuo Chen }; 7491852b37SShuo Chen if (i == 0) 7591852b37SShuo Chen s.start_nano = clock_diff(before, start); 7691852b37SShuo Chen else 7791852b37SShuo Chen s.start_nano = clock_diff(before, now); 7891852b37SShuo Chen rtts.push_back(s); 7991852b37SShuo Chen } 8091852b37SShuo Chen 8191852b37SShuo Chen if (delay_ms > 0) { 8291852b37SShuo Chen ::usleep(delay_ms * 1000); 8391852b37SShuo Chen } 8491852b37SShuo Chen } 8591852b37SShuo Chen return rtts; 8691852b37SShuo Chen} 8791852b37SShuo Chen 8891852b37SShuo Chenint main(int argc, char* argv[]) 8991852b37SShuo Chen{ 9091852b37SShuo Chen int opt; 9191852b37SShuo Chen int delay = 0, length = 3, batch = 4, payload = 1; 9291852b37SShuo Chen bool silent = false; 9391852b37SShuo Chen while ((opt = getopt(argc, argv, "b:d:l:p:s")) != -1) { 9491852b37SShuo Chen switch (opt) { 9591852b37SShuo Chen case 'b': 9691852b37SShuo Chen batch = atoi(optarg); 9791852b37SShuo Chen break; 9891852b37SShuo Chen case 'd': 9991852b37SShuo Chen delay = atoi(optarg); 10091852b37SShuo Chen break; 10191852b37SShuo Chen case 'l': 10291852b37SShuo Chen length = atoi(optarg); 10391852b37SShuo Chen break; 10491852b37SShuo Chen case 'p': 10591852b37SShuo Chen payload = atoi(optarg); 10691852b37SShuo Chen break; 10791852b37SShuo Chen case 's': 10891852b37SShuo Chen silent = true; 10991852b37SShuo Chen break; 11091852b37SShuo Chen default: 11191852b37SShuo Chen ; 11291852b37SShuo Chen } 11391852b37SShuo Chen } 11491852b37SShuo Chen if (optind >= argc) { 11591852b37SShuo Chen fprintf(stderr, "Usage:\nroundtrip_tcp [-b batch_size] [-d delay_ms] [-l length_in_seconds] echo_server_host\n"); 11691852b37SShuo Chen return 1; 11791852b37SShuo Chen } 11891852b37SShuo Chen std::vector<Sample> rtts = run(argv[optind], delay, length, batch, payload); 11991852b37SShuo Chen if (!silent) { 12091852b37SShuo Chen for (Sample s : rtts) { 12191852b37SShuo Chen printf("%d %ld %ld\n", s.index, s.start_nano, s.rtt_nano); 12291852b37SShuo Chen } 12391852b37SShuo Chen } 12491852b37SShuo Chen} 125