1#include "InetAddress.h"
2#include "TcpStream.h"
3
4#include <string.h>
5#include <sys/time.h>
6#include <unistd.h>
7
8double now()
9{
10  struct timeval tv = { 0, 0 };
11  gettimeofday(&tv, NULL);
12  return tv.tv_sec + tv.tv_usec / 1000000.0;
13}
14
15int main(int argc, char* argv[])
16{
17  if (argc < 3)
18  {
19    printf("Usage: %s [-b] [-D] [-n num] hostname message_length\n", argv[0]);
20    printf("  -b Buffering request before sending.\n"
21           "  -D Set TCP_NODELAY.\n"
22           "  -n num Send num concurrent requests, default = 1.\n");
23    return 0;
24  }
25
26  int opt = 0;
27  bool buffering = false;
28  bool tcpnodelay = false;
29  int num = 1;
30  while ( (opt = getopt(argc, argv, "bDn:")) != -1)
31  {
32    switch (opt)
33    {
34      case 'b':
35        buffering = true;
36        break;
37      case 'D':
38        tcpnodelay = true;
39        break;
40      case 'n':
41        num = atoi(optarg);
42        break;
43      default:
44        printf("Unknown option '%c'\n", opt);
45        return 0;
46    }
47  }
48
49  if (optind > argc - 2)
50  {
51    printf("Please specify hostname and message_length.\n");
52    return 0;
53  }
54
55  const char* hostname = argv[optind];
56  int len = atoi(argv[optind+1]);
57
58  const uint16_t port = 3210;
59  InetAddress addr;
60  if (!InetAddress::resolve(hostname, port, &addr))
61  {
62    printf("Unable to resolve %s\n", argv[1]);
63    return 0;
64  }
65
66  printf("connecting to %s\n", addr.toIpPort().c_str());
67  TcpStreamPtr stream(TcpStream::connect(addr));
68  if (!stream)
69  {
70    printf("Unable to connect %s\n", addr.toIpPort().c_str());
71    perror("");
72    return 0;
73  }
74
75  if (tcpnodelay)
76  {
77    stream->setTcpNoDelay(true);
78    printf("connected, set TCP_NODELAY\n");
79  }
80  else
81  {
82    stream->setTcpNoDelay(false);
83    printf("connected\n");
84  }
85
86
87  double start = now();
88  for (int n = 0; n < num; ++n)
89  {
90    printf("Request no. %d, sending %d bytes\n", n, len);
91    if (buffering)
92    {
93      std::vector<char> message(len + sizeof len, 'S');
94      memcpy(message.data(), &len, sizeof len);
95      int nw = stream->sendAll(message.data(), message.size());
96      printf("%.6f sent %d bytes\n", now(), nw);
97    }
98    else
99    {
100      stream->sendAll(&len, sizeof len);
101      printf("%.6f sent header\n", now());
102      usleep(1000); // prevent kernel merging TCP segments
103      std::string payload(len, 'S');
104      int nw = stream->sendAll(payload.data(), payload.size());
105      printf("%.6f sent %d bytes\n", now(), nw);
106    }
107  }
108
109  printf("Sent all %d requests, receiving responses.\n", num);
110  for (int n = 0; n < num; ++n)
111  {
112    int ack = 0;
113    int nr = stream->receiveAll(&ack, sizeof ack);
114    printf("%.6f received %d bytes, ack = %d\n", now(), nr, ack);
115  }
116  printf("total %f seconds\n", now() - start);
117}
118