1726c52daSShuo Chen#include "thread/Atomic.h"
2726c52daSShuo Chen#include "datetime/Timestamp.h"
393e5f6a7SShuo Chen#include "Acceptor.h"
493e5f6a7SShuo Chen#include "InetAddress.h"
593e5f6a7SShuo Chen#include "TcpStream.h"
693e5f6a7SShuo Chen
7d42543f4SShuo Chen#include <string.h>
8d42543f4SShuo Chen
993e5f6a7SShuo Chen#include <thread>
1093e5f6a7SShuo Chen
1193e5f6a7SShuo Chenmuduo::AtomicInt64 g_bytes;
1293e5f6a7SShuo Chen
1393e5f6a7SShuo Chenstd::string getMessage()
1493e5f6a7SShuo Chen{
1593e5f6a7SShuo Chen  std::string line;
1693e5f6a7SShuo Chen  for (int i = 33; i < 127; ++i)
1793e5f6a7SShuo Chen  {
1893e5f6a7SShuo Chen    line.push_back(char(i));
1993e5f6a7SShuo Chen  }
2093e5f6a7SShuo Chen  line += line;
2193e5f6a7SShuo Chen
2293e5f6a7SShuo Chen  std::string message;
2393e5f6a7SShuo Chen  for (size_t i = 0; i < 127-33; ++i)
2493e5f6a7SShuo Chen  {
2593e5f6a7SShuo Chen    message += line.substr(i, 72) + '\n';
2693e5f6a7SShuo Chen  }
2793e5f6a7SShuo Chen  return message;
2893e5f6a7SShuo Chen}
2993e5f6a7SShuo Chen
3093e5f6a7SShuo Chenvoid measure()
3193e5f6a7SShuo Chen{
3293e5f6a7SShuo Chen  muduo::Timestamp start = muduo::Timestamp::now();
3393e5f6a7SShuo Chen  while (true)
3493e5f6a7SShuo Chen  {
3593e5f6a7SShuo Chen    struct timespec ts = { 1, 0 };
3693e5f6a7SShuo Chen    ::nanosleep(&ts, NULL);
3793e5f6a7SShuo Chen    // unfortunately, those two assignments are not atomic
3893e5f6a7SShuo Chen    int64_t bytes = g_bytes.getAndSet(0);
3993e5f6a7SShuo Chen    muduo::Timestamp end = muduo::Timestamp::now();
4093e5f6a7SShuo Chen    double elapsed = timeDifference(end, start);
4193e5f6a7SShuo Chen    start = end;
4293e5f6a7SShuo Chen    if (bytes)
4393e5f6a7SShuo Chen    {
4493e5f6a7SShuo Chen      printf("%.3f MiB/s\n", bytes / (1024.0 * 1024) / elapsed);
4593e5f6a7SShuo Chen    }
4693e5f6a7SShuo Chen  }
4793e5f6a7SShuo Chen}
4893e5f6a7SShuo Chen
4993e5f6a7SShuo Chenvoid chargen(TcpStreamPtr stream)
5093e5f6a7SShuo Chen{
5193e5f6a7SShuo Chen  std::string message = getMessage();
5293e5f6a7SShuo Chen  while (true)
5393e5f6a7SShuo Chen  {
5493e5f6a7SShuo Chen    int nw = stream->sendAll(message.data(), message.size());
5593e5f6a7SShuo Chen    g_bytes.add(nw);
5693e5f6a7SShuo Chen    if (nw < static_cast<int>(message.size()))
5793e5f6a7SShuo Chen    {
5893e5f6a7SShuo Chen      break;
5993e5f6a7SShuo Chen    }
6093e5f6a7SShuo Chen  }
6193e5f6a7SShuo Chen}
6293e5f6a7SShuo Chen
63d42543f4SShuo Chen// a thread-per-connection current chargen server and client
64d42543f4SShuo Chenint main(int argc, char* argv[])
6593e5f6a7SShuo Chen{
66d42543f4SShuo Chen  if (argc < 3)
67d42543f4SShuo Chen  {
68d42543f4SShuo Chen    printf("Usage:\n  %s hostname port\n  %s -l port\n", argv[0], argv[0]);
6914ca1249SShuo Chen    std::string message = getMessage();
7014ca1249SShuo Chen    printf("message size = %zd\n", message.size());
71d42543f4SShuo Chen    return 0;
72d42543f4SShuo Chen  }
73d42543f4SShuo Chen
7493e5f6a7SShuo Chen  std::thread(measure).detach();
75d42543f4SShuo Chen
76d42543f4SShuo Chen  int port = atoi(argv[2]);
77d42543f4SShuo Chen  if (strcmp(argv[1], "-l") == 0)
7893e5f6a7SShuo Chen  {
7924ca08a8SShuo Chen    InetAddress listenAddr(port);
8024ca08a8SShuo Chen    Acceptor acceptor(listenAddr);
81d42543f4SShuo Chen    printf("Accepting... Ctrl-C to exit\n");
82d42543f4SShuo Chen    int count = 0;
83d42543f4SShuo Chen    while (true)
84d42543f4SShuo Chen    {
85d42543f4SShuo Chen      TcpStreamPtr tcpStream = acceptor.accept();
86d42543f4SShuo Chen      printf("accepted no. %d client\n", ++count);
8793e5f6a7SShuo Chen
88d42543f4SShuo Chen      std::thread thr(chargen, std::move(tcpStream));
89d42543f4SShuo Chen      thr.detach();
90d42543f4SShuo Chen    }
91d42543f4SShuo Chen  }
92d42543f4SShuo Chen  else
93d42543f4SShuo Chen  {
9424ca08a8SShuo Chen    InetAddress addr;
95d42543f4SShuo Chen    const char* hostname = argv[1];
9624ca08a8SShuo Chen    if (InetAddress::resolve(hostname, port, &addr))
97d42543f4SShuo Chen    {
98d42543f4SShuo Chen      TcpStreamPtr stream(TcpStream::connect(addr));
99d42543f4SShuo Chen      if (stream)
100d42543f4SShuo Chen      {
101d42543f4SShuo Chen        chargen(std::move(stream));
102d42543f4SShuo Chen      }
103d42543f4SShuo Chen      else
104d42543f4SShuo Chen      {
105d42543f4SShuo Chen        printf("Unable to connect %s\n", addr.toIpPort().c_str());
106d42543f4SShuo Chen        perror("");
107d42543f4SShuo Chen      }
108d42543f4SShuo Chen    }
109d42543f4SShuo Chen    else
110d42543f4SShuo Chen    {
111d42543f4SShuo Chen      printf("Unable to resolve %s\n", hostname);
112d42543f4SShuo Chen    }
11393e5f6a7SShuo Chen  }
11493e5f6a7SShuo Chen}
115