1
0

pingpong_client.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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: 1024
  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 = 1024;
  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_result() {
  34. printf("total readcount=%llu readbytes=%llu\n",
  35. (unsigned long long)total_readcount,
  36. (unsigned long long)total_readbytes);
  37. printf("throughput = %llu MB/s\n", (total_readbytes) / ((unsigned long long)duration * 1024 * 1024));
  38. }
  39. static void on_close(hio_t* io) {
  40. if (++disconnected_num == connections) {
  41. if (verbose) {
  42. printf("all disconnected\n");
  43. }
  44. }
  45. }
  46. static void on_recv(hio_t* io, void* buf, int readbytes) {
  47. ++total_readcount;
  48. total_readbytes += readbytes;
  49. hio_write(io, buf, readbytes);
  50. }
  51. static void on_connect(hio_t* io) {
  52. if (++connected_num == connections) {
  53. if (verbose) {
  54. printf("all connected\n");
  55. }
  56. }
  57. hio_write(io, sendbuf, sendbytes);
  58. hio_setcb_read(io, on_recv);
  59. hio_read_start(io);
  60. }
  61. int main(int argc, char** argv) {
  62. // parse cmdline
  63. main_ctx_init(argc, argv);
  64. int ret = parse_opt(argc, argv, options);
  65. if (ret != 0) {
  66. print_help();
  67. exit(ret);
  68. }
  69. const char* strHost = get_arg("H");
  70. const char* strPort = get_arg("p");
  71. const char* strConnections = get_arg("c");
  72. const char* strDuration = get_arg("d");
  73. const char* strThreads = get_arg("t");
  74. const char* strBytes = get_arg("b");
  75. if (strHost) host = strHost;
  76. if (strPort) port = atoi(strPort);
  77. if (strConnections) connections = atoi(strConnections);
  78. if (strDuration) duration = atoi(strDuration);
  79. if (strThreads) threads = atoi(strThreads);
  80. if (strBytes) sendbytes = atoi(strBytes);
  81. if (get_arg("h") || port == 0) {
  82. print_help();
  83. exit(0);
  84. }
  85. if (get_arg("v")) {
  86. verbose = true;
  87. }
  88. sendbuf = malloc(sendbytes);
  89. printf("[%s:%d] %d threads %d connections run %ds\n",
  90. host, port,
  91. threads, connections, duration);
  92. EventLoopThreadPool loop_threads(threads);
  93. loop_threads.start(true);
  94. for (int i = 0; i < connections; ++i) {
  95. EventLoopPtr loop = loop_threads.nextLoop();
  96. hloop_t* hloop = loop->loop();
  97. loop->runInLoop([hloop](){
  98. hio_t* io = hio_create_socket(hloop, host, port, HIO_TYPE_TCP, HIO_CLIENT_SIDE);
  99. if (io == NULL) {
  100. perror("socket");
  101. exit(1);
  102. }
  103. tcp_nodelay(hio_fd(io), 1);
  104. hio_setcb_connect(io, on_connect);
  105. hio_setcb_close(io, on_close);
  106. hio_connect(io);
  107. });
  108. }
  109. // stop after seconds
  110. loop_threads.loop()->setTimeout(duration * 1000, [&loop_threads](TimerID timerID){
  111. loop_threads.stop(false);
  112. });
  113. // wait loop_threads exit
  114. loop_threads.join();
  115. print_result();
  116. return 0;
  117. }