You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
5.3KB

  1. /*
  2. * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
  3. *
  4. * This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit).
  5. *
  6. * Use of this source code is governed by MIT license that can be found in the
  7. * LICENSE file in the root of the source tree. All contributing project authors
  8. * may be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include <csignal>
  11. #include <iostream>
  12. #include "Util/CMD.h"
  13. #include "Util/logger.h"
  14. #include "Util/util.h"
  15. #include "Network/Session.h"
  16. #include "Network/TcpServer.h"
  17. using namespace std;
  18. using namespace toolkit;
  19. /**
  20. * 回显会话
  21. */
  22. class EchoSession : public Session {
  23. public:
  24. EchoSession(const Socket::Ptr &pSock) : Session(pSock){
  25. DebugL;
  26. }
  27. virtual ~EchoSession(){
  28. DebugL;
  29. }
  30. void onRecv(const Buffer::Ptr &buffer) override {
  31. send(buffer);
  32. }
  33. void onError(const SockException &err) override{
  34. WarnL << err.what();
  35. }
  36. void onManager() override {}
  37. };
  38. //命令(http)
  39. class CMD_pingpong: public CMD {
  40. public:
  41. CMD_pingpong(){
  42. _parser.reset(new OptionParser(nullptr));
  43. (*_parser) << Option('l', "listen", Option::ArgRequired, "10000", false, "服务器模式:监听端口", nullptr);
  44. //测试客户端个数,默认10个
  45. (*_parser) << Option('c', "count", Option::ArgRequired, to_string(10).data(), false, "客户端模式:测试客户端个数", nullptr);
  46. //默认每次发送1MB的数据
  47. (*_parser) << Option('b', "block", Option::ArgRequired, to_string(1024 * 1024).data(), false, "客户端模式:测试数据块大小", nullptr);
  48. //默认1秒发送10次,总速度率为1MB/s * 10 * 10 = 100MB/s
  49. (*_parser) << Option('i', "interval", Option::ArgRequired, to_string(100).data(), false, "客户端模式:测试数据发送间隔,单位毫秒", nullptr);
  50. //客户端启动间隔时间
  51. (*_parser) << Option('d', "delay", Option::ArgRequired, "50", false, "服务器模式:客户端启动间隔时间", nullptr);
  52. //指定服务器地址
  53. (*_parser) << Option('s', "server", Option::ArgRequired, "127.0.0.1:10000", false, "客户端模式:测试服务器地址", []
  54. (const std::shared_ptr<ostream> &stream, const string &arg) {
  55. if (arg.find(":") == string::npos) {
  56. //中断后续选项的解析以及解析完毕回调等操作
  57. throw std::runtime_error("\t地址必须指明端口号.");
  58. }
  59. //如果返回false则忽略后续选项的解析
  60. return true;
  61. });
  62. }
  63. ~CMD_pingpong() {}
  64. const char *description() const override {
  65. return "tcp回显性能测试";
  66. }
  67. };
  68. EventPoller::Ptr nextPoller(){
  69. static vector<EventPoller::Ptr> s_poller_vec;
  70. static int s_poller_index = 0;
  71. if(s_poller_vec.empty()){
  72. EventPollerPool::Instance().for_each([&](const TaskExecutor::Ptr &executor){
  73. s_poller_vec.emplace_back(dynamic_pointer_cast<EventPoller>(executor));
  74. });
  75. }
  76. auto ret = s_poller_vec[s_poller_index++];
  77. if(s_poller_index == s_poller_vec.size()){
  78. s_poller_index = 0;
  79. }
  80. return ret;
  81. }
  82. int main(int argc,char *argv[]){
  83. CMD_pingpong cmd;
  84. try{
  85. cmd(argc,argv);
  86. }catch (std::exception &ex){
  87. cout << ex.what() << endl;
  88. return 0;
  89. }
  90. //初始化环境
  91. Logger::Instance().add(std::shared_ptr<ConsoleChannel>(new ConsoleChannel()));
  92. Logger::Instance().setWriter(std::shared_ptr<LogWriter>(new AsyncLogWriter()));
  93. {
  94. int interval = cmd["interval"];
  95. int block = cmd["block"];
  96. auto ip = cmd.splitedVal("server")[0];
  97. int port = cmd.splitedVal("server")[1];
  98. int delay = cmd["delay"];
  99. auto buffer = BufferRaw::create();
  100. buffer->setCapacity(block);
  101. buffer->setSize(block);
  102. TcpServer::Ptr server(new TcpServer);
  103. server->start<EchoSession>(cmd["listen"]);
  104. for(auto i = 0; i < cmd["count"].as<int>() ; ++i){
  105. auto poller = nextPoller();
  106. auto socket = Socket::createSocket(poller, false);
  107. socket->connect(ip,port,[socket,poller,interval,buffer](const SockException &err){
  108. if(err){
  109. WarnL << err.what();
  110. return;
  111. }
  112. socket->setOnErr([](const SockException &err){
  113. WarnL << err.what();
  114. });
  115. socket->setOnRead([interval,socket](const Buffer::Ptr &buffer, struct sockaddr *addr , int addr_len){
  116. if(!interval){
  117. socket->send(buffer);
  118. }
  119. });
  120. if(interval){
  121. poller->doDelayTask(interval,[socket,interval,buffer](){
  122. socket->send(buffer);
  123. return interval;
  124. });
  125. }else{
  126. socket->send(buffer);
  127. }
  128. });
  129. usleep(delay * 1000);
  130. }
  131. //设置退出信号处理函数
  132. static semaphore sem;
  133. signal(SIGINT, [](int) { sem.post(); });// 设置退出信号
  134. sem.wait();
  135. }
  136. return 0;
  137. }