1569528b0SShuo Chen#include "InetAddress.h"
2569528b0SShuo Chen#include "TcpStream.h"
3569528b0SShuo Chen
4569528b0SShuo Chen#include <string.h>
5569528b0SShuo Chen#include <sys/time.h>
6569528b0SShuo Chen#include <unistd.h>
7569528b0SShuo Chen
8569528b0SShuo Chendouble now()
9569528b0SShuo Chen{
10569528b0SShuo Chen  struct timeval tv = { 0, 0 };
11569528b0SShuo Chen  gettimeofday(&tv, NULL);
12569528b0SShuo Chen  return tv.tv_sec + tv.tv_usec / 1000000.0;
13569528b0SShuo Chen}
14569528b0SShuo Chen
15569528b0SShuo Chenint main(int argc, char* argv[])
16569528b0SShuo Chen{
17569528b0SShuo Chen  if (argc < 3)
18569528b0SShuo Chen  {
19b42ce01eSShuo Chen    printf("Usage: %s [-b] [-D] [-n num] hostname message_length\n", argv[0]);
20b42ce01eSShuo Chen    printf("  -b Buffering request before sending.\n"
21b42ce01eSShuo Chen           "  -D Set TCP_NODELAY.\n"
22b42ce01eSShuo Chen           "  -n num Send num concurrent requests, default = 1.\n");
23569528b0SShuo Chen    return 0;
24569528b0SShuo Chen  }
25569528b0SShuo Chen
26569528b0SShuo Chen  int opt = 0;
27569528b0SShuo Chen  bool buffering = false;
28569528b0SShuo Chen  bool tcpnodelay = false;
29b42ce01eSShuo Chen  int num = 1;
30b42ce01eSShuo Chen  while ( (opt = getopt(argc, argv, "bDn:")) != -1)
31569528b0SShuo Chen  {
32569528b0SShuo Chen    switch (opt)
33569528b0SShuo Chen    {
34569528b0SShuo Chen      case 'b':
35569528b0SShuo Chen        buffering = true;
36569528b0SShuo Chen        break;
37569528b0SShuo Chen      case 'D':
38569528b0SShuo Chen        tcpnodelay = true;
39569528b0SShuo Chen        break;
40b42ce01eSShuo Chen      case 'n':
41b42ce01eSShuo Chen        num = atoi(optarg);
42b42ce01eSShuo Chen        break;
43569528b0SShuo Chen      default:
44569528b0SShuo Chen        printf("Unknown option '%c'\n", opt);
45569528b0SShuo Chen        return 0;
46569528b0SShuo Chen    }
47569528b0SShuo Chen  }
48569528b0SShuo Chen
49569528b0SShuo Chen  if (optind > argc - 2)
50569528b0SShuo Chen  {
51569528b0SShuo Chen    printf("Please specify hostname and message_length.\n");
52569528b0SShuo Chen    return 0;
53569528b0SShuo Chen  }
54569528b0SShuo Chen
55569528b0SShuo Chen  const char* hostname = argv[optind];
56569528b0SShuo Chen  int len = atoi(argv[optind+1]);
57569528b0SShuo Chen
5824ca08a8SShuo Chen  const uint16_t port = 3210;
5924ca08a8SShuo Chen  InetAddress addr;
6024ca08a8SShuo Chen  if (!InetAddress::resolve(hostname, port, &addr))
61569528b0SShuo Chen  {
62569528b0SShuo Chen    printf("Unable to resolve %s\n", argv[1]);
63569528b0SShuo Chen    return 0;
64569528b0SShuo Chen  }
65569528b0SShuo Chen
66569528b0SShuo Chen  printf("connecting to %s\n", addr.toIpPort().c_str());
67569528b0SShuo Chen  TcpStreamPtr stream(TcpStream::connect(addr));
68569528b0SShuo Chen  if (!stream)
69569528b0SShuo Chen  {
70569528b0SShuo Chen    printf("Unable to connect %s\n", addr.toIpPort().c_str());
71569528b0SShuo Chen    perror("");
72569528b0SShuo Chen    return 0;
73569528b0SShuo Chen  }
74569528b0SShuo Chen
75569528b0SShuo Chen  if (tcpnodelay)
76569528b0SShuo Chen  {
77569528b0SShuo Chen    stream->setTcpNoDelay(true);
78569528b0SShuo Chen    printf("connected, set TCP_NODELAY\n");
79569528b0SShuo Chen  }
80569528b0SShuo Chen  else
81569528b0SShuo Chen  {
82569528b0SShuo Chen    stream->setTcpNoDelay(false);
83569528b0SShuo Chen    printf("connected\n");
84569528b0SShuo Chen  }
85569528b0SShuo Chen
86569528b0SShuo Chen
87569528b0SShuo Chen  double start = now();
88b42ce01eSShuo Chen  for (int n = 0; n < num; ++n)
89569528b0SShuo Chen  {
90b42ce01eSShuo Chen    printf("Request no. %d, sending %d bytes\n", n, len);
91b42ce01eSShuo Chen    if (buffering)
92b42ce01eSShuo Chen    {
93b42ce01eSShuo Chen      std::vector<char> message(len + sizeof len, 'S');
94b42ce01eSShuo Chen      memcpy(message.data(), &len, sizeof len);
95b42ce01eSShuo Chen      int nw = stream->sendAll(message.data(), message.size());
96b42ce01eSShuo Chen      printf("%.6f sent %d bytes\n", now(), nw);
97b42ce01eSShuo Chen    }
98b42ce01eSShuo Chen    else
99b42ce01eSShuo Chen    {
100b42ce01eSShuo Chen      stream->sendAll(&len, sizeof len);
101b42ce01eSShuo Chen      printf("%.6f sent header\n", now());
102b42ce01eSShuo Chen      usleep(1000); // prevent kernel merging TCP segments
103b42ce01eSShuo Chen      std::string payload(len, 'S');
104b42ce01eSShuo Chen      int nw = stream->sendAll(payload.data(), payload.size());
105b42ce01eSShuo Chen      printf("%.6f sent %d bytes\n", now(), nw);
106b42ce01eSShuo Chen    }
107569528b0SShuo Chen  }
108b42ce01eSShuo Chen
109b42ce01eSShuo Chen  printf("Sent all %d requests, receiving responses.\n", num);
110b42ce01eSShuo Chen  for (int n = 0; n < num; ++n)
111569528b0SShuo Chen  {
112b42ce01eSShuo Chen    int ack = 0;
113b42ce01eSShuo Chen    int nr = stream->receiveAll(&ack, sizeof ack);
114b42ce01eSShuo Chen    printf("%.6f received %d bytes, ack = %d\n", now(), nr, ack);
115569528b0SShuo Chen  }
116b42ce01eSShuo Chen  printf("total %f seconds\n", now() - start);
117569528b0SShuo Chen}
118