1726c52daSShuo Chen#include "thread/Atomic.h"
2726c52daSShuo Chen#include "datetime/Timestamp.h"
3d42543f4SShuo Chen#include "Acceptor.h"
4d42543f4SShuo Chen#include "InetAddress.h"
5d42543f4SShuo Chen#include "TcpStream.h"
6d42543f4SShuo Chen
7d42543f4SShuo Chen#include <string.h>
8d42543f4SShuo Chen
9d42543f4SShuo Chen#include <thread>
10d42543f4SShuo Chen
11d42543f4SShuo Chenmuduo::AtomicInt64 g_bytes;
12d42543f4SShuo Chen
13d42543f4SShuo Chenvoid measure()
14d42543f4SShuo Chen{
15d42543f4SShuo Chen  muduo::Timestamp start = muduo::Timestamp::now();
16d42543f4SShuo Chen  while (true)
17d42543f4SShuo Chen  {
18d42543f4SShuo Chen    struct timespec ts = { 1, 0 };
19d42543f4SShuo Chen    ::nanosleep(&ts, NULL);
20d42543f4SShuo Chen    // unfortunately, those two assignments are not atomic
21d42543f4SShuo Chen    int64_t bytes = g_bytes.getAndSet(0);
22d42543f4SShuo Chen    muduo::Timestamp end = muduo::Timestamp::now();
23d42543f4SShuo Chen    double elapsed = timeDifference(end, start);
24d42543f4SShuo Chen    start = end;
25d42543f4SShuo Chen    if (bytes)
26d42543f4SShuo Chen    {
27d42543f4SShuo Chen      printf("%.3f MiB/s\n", bytes / (1024.0 * 1024) / elapsed);
28d42543f4SShuo Chen    }
29d42543f4SShuo Chen  }
30d42543f4SShuo Chen}
31d42543f4SShuo Chen
32d42543f4SShuo Chenvoid discard(TcpStreamPtr stream)
33d42543f4SShuo Chen{
34d42543f4SShuo Chen  char buf[65536];
35d42543f4SShuo Chen  while (true)
36d42543f4SShuo Chen  {
37d42543f4SShuo Chen    int nr = stream->receiveSome(buf, sizeof buf);
38d42543f4SShuo Chen    if (nr <= 0)
39d42543f4SShuo Chen      break;
40d42543f4SShuo Chen    g_bytes.add(nr);
41d42543f4SShuo Chen  }
42d42543f4SShuo Chen}
43d42543f4SShuo Chen
44d42543f4SShuo Chen// a thread-per-connection current discard server and client
45d42543f4SShuo Chenint main(int argc, char* argv[])
46d42543f4SShuo Chen{
47d42543f4SShuo Chen  if (argc < 3)
48d42543f4SShuo Chen  {
4924ca08a8SShuo Chen    printf("Usage:\n  %s hostname port\n  %s -l port [-6]\n", argv[0], argv[0]);
50d42543f4SShuo Chen    return 0;
51d42543f4SShuo Chen  }
52d42543f4SShuo Chen
53d42543f4SShuo Chen  std::thread(measure).detach();
54d42543f4SShuo Chen
55d42543f4SShuo Chen  int port = atoi(argv[2]);
56d42543f4SShuo Chen  if (strcmp(argv[1], "-l") == 0)
57d42543f4SShuo Chen  {
5824ca08a8SShuo Chen    const bool ipv6 = (argc > 3 && strcmp(argv[3], "-6") == 0);
5924ca08a8SShuo Chen    Acceptor acceptor((InetAddress(port, ipv6)));
60d42543f4SShuo Chen    printf("Accepting... Ctrl-C to exit\n");
61d42543f4SShuo Chen    int count = 0;
62d42543f4SShuo Chen    while (true)
63d42543f4SShuo Chen    {
64d42543f4SShuo Chen      TcpStreamPtr tcpStream = acceptor.accept();
6524ca08a8SShuo Chen      printf("accepted no. %d client: %s <- %s\n", ++count,
6624ca08a8SShuo Chen             tcpStream->getLocalAddr().toIpPort().c_str(),
6724ca08a8SShuo Chen             tcpStream->getPeerAddr().toIpPort().c_str());
68d42543f4SShuo Chen
69d42543f4SShuo Chen      std::thread thr(discard, std::move(tcpStream));
70d42543f4SShuo Chen      thr.detach();
71d42543f4SShuo Chen    }
72d42543f4SShuo Chen  }
73d42543f4SShuo Chen  else
74d42543f4SShuo Chen  {
7524ca08a8SShuo Chen    InetAddress addr;
76d42543f4SShuo Chen    const char* hostname = argv[1];
7724ca08a8SShuo Chen    if (InetAddress::resolve(hostname, port, &addr))
78d42543f4SShuo Chen    {
79d42543f4SShuo Chen      TcpStreamPtr stream(TcpStream::connect(addr));
80d42543f4SShuo Chen      if (stream)
81d42543f4SShuo Chen      {
82d42543f4SShuo Chen        discard(std::move(stream));
83d42543f4SShuo Chen      }
84d42543f4SShuo Chen      else
85d42543f4SShuo Chen      {
86d42543f4SShuo Chen        printf("Unable to connect %s\n", addr.toIpPort().c_str());
87d42543f4SShuo Chen        perror("");
88d42543f4SShuo Chen      }
89d42543f4SShuo Chen    }
90d42543f4SShuo Chen    else
91d42543f4SShuo Chen    {
92d42543f4SShuo Chen      printf("Unable to resolve %s\n", hostname);
93d42543f4SShuo Chen    }
94d42543f4SShuo Chen  }
95d42543f4SShuo Chen}
96