udp_client.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. //
  2. // udp_client.cpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #include <boost/asio/ip/udp.hpp>
  11. #include <boost/date_time/posix_time/posix_time_types.hpp>
  12. #include <algorithm>
  13. #include <cstdio>
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <vector>
  17. #include "high_res_clock.hpp"
  18. using boost::asio::ip::udp;
  19. using boost::posix_time::ptime;
  20. using boost::posix_time::microsec_clock;
  21. const int num_samples = 100000;
  22. int main(int argc, char* argv[])
  23. {
  24. if (argc != 6)
  25. {
  26. std::fprintf(stderr,
  27. "Usage: udp_client <ip> <port1> "
  28. "<nports> <bufsize> {spin|block}\n");
  29. return 1;
  30. }
  31. const char* ip = argv[1];
  32. unsigned short first_port = static_cast<unsigned short>(std::atoi(argv[2]));
  33. unsigned short num_ports = static_cast<unsigned short>(std::atoi(argv[3]));
  34. std::size_t buf_size = static_cast<std::size_t>(std::atoi(argv[4]));
  35. bool spin = (std::strcmp(argv[5], "spin") == 0);
  36. boost::asio::io_context io_context;
  37. udp::socket socket(io_context, udp::endpoint(udp::v4(), 0));
  38. if (spin)
  39. {
  40. socket.non_blocking(true);
  41. }
  42. udp::endpoint target(boost::asio::ip::make_address(ip), first_port);
  43. unsigned short last_port = first_port + num_ports - 1;
  44. std::vector<unsigned char> write_buf(buf_size);
  45. std::vector<unsigned char> read_buf(buf_size);
  46. ptime start = microsec_clock::universal_time();
  47. boost::uint64_t start_hr = high_res_clock();
  48. boost::uint64_t samples[num_samples];
  49. for (int i = 0; i < num_samples; ++i)
  50. {
  51. boost::uint64_t t = high_res_clock();
  52. boost::system::error_code ec;
  53. socket.send_to(boost::asio::buffer(write_buf), target, 0, ec);
  54. do socket.receive(boost::asio::buffer(read_buf), 0, ec);
  55. while (ec == boost::asio::error::would_block);
  56. samples[i] = high_res_clock() - t;
  57. if (target.port() == last_port)
  58. target.port(first_port);
  59. else
  60. target.port(target.port() + 1);
  61. }
  62. ptime stop = microsec_clock::universal_time();
  63. boost::uint64_t stop_hr = high_res_clock();
  64. boost::uint64_t elapsed_usec = (stop - start).total_microseconds();
  65. boost::uint64_t elapsed_hr = stop_hr - start_hr;
  66. double scale = 1.0 * elapsed_usec / elapsed_hr;
  67. std::sort(samples, samples + num_samples);
  68. std::printf(" 0.0%%\t%f\n", samples[0] * scale);
  69. std::printf(" 0.1%%\t%f\n", samples[num_samples / 1000 - 1] * scale);
  70. std::printf(" 1.0%%\t%f\n", samples[num_samples / 100 - 1] * scale);
  71. std::printf(" 10.0%%\t%f\n", samples[num_samples / 10 - 1] * scale);
  72. std::printf(" 20.0%%\t%f\n", samples[num_samples * 2 / 10 - 1] * scale);
  73. std::printf(" 30.0%%\t%f\n", samples[num_samples * 3 / 10 - 1] * scale);
  74. std::printf(" 40.0%%\t%f\n", samples[num_samples * 4 / 10 - 1] * scale);
  75. std::printf(" 50.0%%\t%f\n", samples[num_samples * 5 / 10 - 1] * scale);
  76. std::printf(" 60.0%%\t%f\n", samples[num_samples * 6 / 10 - 1] * scale);
  77. std::printf(" 70.0%%\t%f\n", samples[num_samples * 7 / 10 - 1] * scale);
  78. std::printf(" 80.0%%\t%f\n", samples[num_samples * 8 / 10 - 1] * scale);
  79. std::printf(" 90.0%%\t%f\n", samples[num_samples * 9 / 10 - 1] * scale);
  80. std::printf(" 99.0%%\t%f\n", samples[num_samples * 99 / 100 - 1] * scale);
  81. std::printf(" 99.9%%\t%f\n", samples[num_samples * 999 / 1000 - 1] * scale);
  82. std::printf("100.0%%\t%f\n", samples[num_samples - 1] * scale);
  83. double total = 0.0;
  84. for (int i = 0; i < num_samples; ++i) total += samples[i] * scale;
  85. std::printf(" mean\t%f\n", total / num_samples);
  86. }