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