1
0

pingpong_client.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include "hv/hmain.h" // import parse_opt
  2. #include "hv/hloop.h"
  3. #include "hv/hsocket.h"
  4. #include "hv/EventLoopThreadPool.h"
  5. using namespace hv;
  6. static const char options[] = "hvH:p:c:d:t:b:";
  7. static const char detail_options[] = R"(
  8. -h Print help infomation
  9. -v Show verbose infomation
  10. -H <Host> default 127.0.0.1
  11. -p <port>
  12. -c <connections> Number of connections, default: 1000
  13. -d <duration> Duration of test, default: 10s
  14. -t <threads> Number of threads, default: 4
  15. -b <bytes> Bytes of send buffer, default: 4096
  16. )";
  17. static int connections = 1000;
  18. static int duration = 10;
  19. static int threads = 4;
  20. static bool verbose = false;
  21. static const char* host = "127.0.0.1";
  22. static int port = 0;
  23. static int sendbytes = 4096;
  24. static void* sendbuf = NULL;
  25. static std::atomic<int> connected_num(0);
  26. static std::atomic<int> disconnected_num(0);
  27. static std::atomic<uint64_t> total_readcount(0);
  28. static std::atomic<uint64_t> total_readbytes(0);
  29. static void print_help() {
  30. printf("Usage: %s [%s]\n", g_main_ctx.program_name, options);
  31. printf("Options:\n%s\n", detail_options);
  32. }
  33. static void print_cmd() {
  34. printf("Running %ds test @ %s:%d\n", duration, host, port);
  35. printf("%d threads and %d connections, send %d bytes each time\n", threads, connections, sendbytes);
  36. }
  37. static void print_result() {
  38. printf("total readcount=%llu readbytes=%llu\n",
  39. (unsigned long long)total_readcount,
  40. (unsigned long long)total_readbytes);
  41. printf("throughput = %llu MB/s\n", (total_readbytes) / ((unsigned long long)duration * 1024 * 1024));
  42. }
  43. static void on_close(hio_t* io) {
  44. if (++disconnected_num == connections) {
  45. if (verbose) {
  46. printf("all disconnected\n");
  47. }
  48. }
  49. }
  50. static void on_recv(hio_t* io, void* buf, int readbytes) {
  51. ++total_readcount;
  52. total_readbytes += readbytes;
  53. hio_write(io, buf, readbytes);
  54. }
  55. static void on_connect(hio_t* io) {
  56. if (++connected_num == connections) {
  57. if (verbose) {
  58. printf("all connected\n");
  59. }
  60. }
  61. hio_write(io, sendbuf, sendbytes);
  62. hio_setcb_read(io, on_recv);
  63. hio_read_start(io);
  64. }
  65. static void start_connect(hloop_t* loop) {
  66. hio_t* io = hio_create_socket(loop, host, port, HIO_TYPE_TCP, HIO_CLIENT_SIDE);
  67. if (io == NULL) {
  68. perror("socket");
  69. exit(1);
  70. }
  71. tcp_nodelay(hio_fd(io), 1);
  72. hio_setcb_connect(io, on_connect);
  73. hio_setcb_close(io, on_close);
  74. hio_connect(io);
  75. }
  76. int main(int argc, char** argv) {
  77. // parse cmdline
  78. main_ctx_init(argc, argv);
  79. int ret = parse_opt(argc, argv, options);
  80. if (ret != 0) {
  81. print_help();
  82. exit(ret);
  83. }
  84. const char* strHost = get_arg("H");
  85. const char* strPort = get_arg("p");
  86. const char* strConnections = get_arg("c");
  87. const char* strDuration = get_arg("d");
  88. const char* strThreads = get_arg("t");
  89. const char* strBytes = get_arg("b");
  90. if (strHost) host = strHost;
  91. if (strPort) port = atoi(strPort);
  92. if (strConnections) connections = atoi(strConnections);
  93. if (strDuration) duration = atoi(strDuration);
  94. if (strThreads) threads = atoi(strThreads);
  95. if (strBytes) sendbytes = atoi(strBytes);
  96. if (get_arg("h") || port == 0) {
  97. print_help();
  98. exit(0);
  99. }
  100. if (get_arg("v")) {
  101. verbose = true;
  102. }
  103. sendbuf = malloc(sendbytes);
  104. print_cmd();
  105. EventLoopThreadPool loop_threads(threads);
  106. loop_threads.start(true);
  107. for (int i = 0; i < connections; ++i) {
  108. EventLoopPtr loop = loop_threads.nextLoop();
  109. loop->runInLoop(std::bind(start_connect, loop->loop()));
  110. }
  111. // stop after seconds
  112. loop_threads.loop()->setTimeout(duration * 1000, [&loop_threads](TimerID timerID){
  113. loop_threads.stop(false);
  114. });
  115. // wait loop_threads exit
  116. loop_threads.join();
  117. print_result();
  118. return 0;
  119. }