Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

180 linhas
6.7KB

  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 <iostream>
  11. #include "Util/CMD.h"
  12. #include "Util/logger.h"
  13. #include "Util/util.h"
  14. #include "Network/TcpClient.h"
  15. #include <csignal>
  16. using namespace std;
  17. using namespace toolkit;
  18. class TestClient: public TcpClient {
  19. public:
  20. using Ptr = std::shared_ptr<TestClient>;
  21. TestClient() : TcpClient(){}
  22. ~TestClient(){}
  23. void connect(const string &strUrl, uint16_t iPort,float fTimeoutSec){
  24. startConnect(strUrl,iPort,fTimeoutSec);
  25. }
  26. void disconnect(){
  27. shutdown();
  28. }
  29. size_t commit(const string &method,const string &path,const string &host) {
  30. string strGet = StrPrinter
  31. << method
  32. << " "
  33. << path
  34. << " HTTP/1.1\r\n"
  35. << "Host: " << host << "\r\n"
  36. << "Connection: keep-alive\r\n"
  37. << "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) "
  38. "AppleWebKit/537.36 (KHTML, like Gecko) "
  39. "Chrome/58.0.3029.110 Safari/537.36\r\n"
  40. << "Accept-Encoding: gzip, deflate, sdch\r\n"
  41. << "Accept-Language: zh-CN,zh;q=0.8,en;q=0.6\r\n\r\n";
  42. DebugL << "\r\n" << strGet;
  43. return SockSender::send(strGet);
  44. }
  45. protected:
  46. virtual void onConnect(const SockException &ex) override{
  47. //连接结果事件
  48. InfoL << (ex ? ex.what() : "success");
  49. }
  50. virtual void onRecv(const Buffer::Ptr &pBuf) override{
  51. //接收数据事件
  52. DebugL << pBuf->data();
  53. }
  54. virtual void onFlush() override{
  55. //发送阻塞后,缓存清空事件
  56. DebugL;
  57. }
  58. virtual void onErr(const SockException &ex) override{
  59. //断开连接事件,一般是EOF
  60. WarnL << ex.what();
  61. }
  62. };
  63. //命令(http)
  64. class CMD_http: public CMD {
  65. public:
  66. CMD_http(){
  67. _client.reset(new TestClient);
  68. _parser.reset(new OptionParser([this](const std::shared_ptr<ostream> &stream,mINI &args){
  69. //所有选项解析完毕后触发该回调,我们可以在这里做一些全局的操作
  70. if(hasKey("connect")){
  71. //发起连接操作
  72. connect(stream);
  73. return;
  74. }
  75. if(hasKey("commit")){
  76. commit(stream);
  77. return;
  78. }
  79. }));
  80. (*_parser) << Option('T', "type", Option::ArgRequired, nullptr, true, "应用程序模式,0:传统模式,1:shell模式", nullptr);
  81. (*_parser) << Option('s',/*该选项简称,如果是\x00则说明无简称*/
  82. "server",/*该选项全称,每个选项必须有全称;不得为null或空字符串*/
  83. Option::ArgRequired,/*该选项后面必须跟值*/
  84. "www.baidu.com:80",/*该选项默认值*/
  85. false,/*该选项是否必须赋值,如果没有默认值且为ArgRequired时用户必须提供该参数否则将抛异常*/
  86. "tcp服务器地址,以冒号分隔端口号",/*该选项说明文字*/
  87. [this](const std::shared_ptr<ostream> &stream, const string &arg){/*解析到该选项的回调*/
  88. if(arg.find(":") == string::npos){
  89. //中断后续选项的解析以及解析完毕回调等操作
  90. throw std::runtime_error("\t地址必须指明端口号.");
  91. }
  92. //如果返回false则忽略后续选项的解析
  93. return true;
  94. });
  95. (*_parser) << Option('d', "disconnect", Option::ArgNone, nullptr ,false, "是否断开连接",
  96. [this](const std::shared_ptr<ostream> &stream, const string &arg){
  97. //断开连接操作,所以后续的参数我们都不解析了
  98. disconnect(stream);
  99. return false;
  100. });
  101. (*_parser) << Option('c', "connect", Option::ArgNone, nullptr, false, "发起tcp connect操作", nullptr);
  102. (*_parser) << Option('t', "time_out", Option::ArgRequired, "3",false, "连接超时间", nullptr);
  103. (*_parser) << Option('m', "method", Option::ArgRequired, "GET",false, "HTTP方法,譬如GET、POST", nullptr);
  104. (*_parser) << Option('p', "path", Option::ArgRequired, "/index.html",false, "HTTP url路径", nullptr);
  105. (*_parser) << Option('C', "commit", Option::ArgNone, nullptr, false, "提交HTTP请求", nullptr);
  106. }
  107. ~CMD_http() {}
  108. const char *description() const override {
  109. return "http测试客户端";
  110. }
  111. private:
  112. void connect(const std::shared_ptr<ostream> &stream){
  113. (*stream) << "connect操作" << endl;
  114. _client->connect(splitedVal("server")[0],splitedVal("server")[1],(*this)["time_out"]);
  115. }
  116. void disconnect(const std::shared_ptr<ostream> &stream){
  117. (*stream) << "disconnect操作" << endl;
  118. _client->disconnect();
  119. }
  120. void commit(const std::shared_ptr<ostream> &stream){
  121. (*stream) << "commit操作" << endl;
  122. _client->commit((*this)["method"],(*this)["path"],(*this)["server"]);
  123. }
  124. private:
  125. TestClient::Ptr _client;
  126. };
  127. int main(int argc,char *argv[]){
  128. REGIST_CMD(http);
  129. signal(SIGINT,[](int ){
  130. exit(0);
  131. });
  132. try{
  133. CMD_DO("http",argc,argv);
  134. }catch (std::exception &ex){
  135. cout << ex.what() << endl;
  136. return 0;
  137. }
  138. if(GET_CMD("http")["type"] == 0){
  139. cout << "传统模式,已退出程序,请尝试shell模式" << endl;
  140. return 0;
  141. }
  142. GET_CMD("http").delOption("type");
  143. //初始化环境
  144. Logger::Instance().add(std::shared_ptr<ConsoleChannel>(new ConsoleChannel()));
  145. Logger::Instance().setWriter(std::shared_ptr<LogWriter>(new AsyncLogWriter()));
  146. cout << "> 欢迎进入命令模式,你可以输入\"help\"命令获取帮助" << endl;
  147. string cmd_line;
  148. while(cin.good()){
  149. try{
  150. cout << "> ";
  151. getline(cin,cmd_line);
  152. CMDRegister::Instance()(cmd_line);
  153. }catch (ExitException &){
  154. break;
  155. }catch (std::exception &ex){
  156. cout << ex.what() << endl;
  157. }
  158. }
  159. return 0;
  160. }