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

191 lines
7.6 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
*
* This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#include <iostream>
#include "Util/CMD.h"
#include "Util/logger.h"
#include "Util/util.h"
#include "Network/TcpClient.h"
#include <csignal>
using namespace std;
using namespace toolkit;
class TestClient: public TcpClient {
public:
using Ptr = std::shared_ptr<TestClient>;
TestClient() : TcpClient(){}
~TestClient(){}
void connect(const string &strUrl, uint16_t iPort,float fTimeoutSec){
startConnect(strUrl,iPort,fTimeoutSec);
}
void disconnect(){
shutdown();
}
size_t commit(const string &method,const string &path,const string &host) {
string strGet = StrPrinter
<< method
<< " "
<< path
<< " HTTP/1.1\r\n"
<< "Host: " << host << "\r\n"
<< "Connection: keep-alive\r\n"
<< "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/58.0.3029.110 Safari/537.36\r\n"
<< "Accept-Encoding: gzip, deflate, sdch\r\n"
<< "Accept-Language: zh-CN,zh;q=0.8,en;q=0.6\r\n\r\n";
DebugL << "\r\n" << strGet;
return SockSender::send(strGet);
}
protected:
virtual void onConnect(const SockException &ex) override{
//连接结果事件 [AUTO-TRANSLATED:46887902]
// Connection established event
InfoL << (ex ? ex.what() : "success");
}
virtual void onRecv(const Buffer::Ptr &pBuf) override{
//接收数据事件 [AUTO-TRANSLATED:397ef7e4]
// Data received event
DebugL << pBuf->data();
}
virtual void onFlush() override{
//发送阻塞后,缓存清空事件 [AUTO-TRANSLATED:46e8bca0]
// Buffer cleared after send blocking event
DebugL;
}
virtual void onError(const SockException &ex) override{
//断开连接事件一般是EOF [AUTO-TRANSLATED:7359fecf]
// Disconnected event, usually EOF
WarnL << ex;
}
};
//命令(http) [AUTO-TRANSLATED:d96c7331]
// Command (http)
class CMD_http: public CMD {
public:
CMD_http(){
_client.reset(new TestClient);
_parser.reset(new OptionParser([this](const std::shared_ptr<ostream> &stream,mINI &args){
//所有选项解析完毕后触发该回调,我们可以在这里做一些全局的操作 [AUTO-TRANSLATED:cce43d55]
// All options parsed, trigger this callback, we can do some global operations here
if(hasKey("connect")){
//发起连接操作 [AUTO-TRANSLATED:405329cf]
// Initiate connection operation
connect(stream);
return;
}
if(hasKey("commit")){
commit(stream);
return;
}
}));
(*_parser) << Option('T', "type", Option::ArgRequired, nullptr, true, "应用程序模式0传统模式1shell模式", nullptr);
(*_parser) << Option('s',/*该选项简称,如果是\x00则说明无简称*/
"server",/*该选项全称,每个选项必须有全称不得为null或空字符串*/
Option::ArgRequired,/*该选项后面必须跟值*/
"www.baidu.com:80",/*该选项默认值*/
false,/*该选项是否必须赋值如果没有默认值且为ArgRequired时用户必须提供该参数否则将抛异常*/
"tcp服务器地址以冒号分隔端口号",/*该选项说明文字*/
[this](const std::shared_ptr<ostream> &stream, const string &arg){/*解析到该选项的回调*/
if(arg.find(":") == string::npos){
//中断后续选项的解析以及解析完毕回调等操作 [AUTO-TRANSLATED:15b7592f]
// Interrupt subsequent option parsing and parsing completion callback operations
throw std::runtime_error("\t地址必须指明端口号.");
}
//如果返回false则忽略后续选项的解析 [AUTO-TRANSLATED:01a3d6bc]
// If return false, ignore subsequent option parsing
return true;
});
(*_parser) << Option('d', "disconnect", Option::ArgNone, nullptr ,false, "是否断开连接",
[this](const std::shared_ptr<ostream> &stream, const string &arg){
//断开连接操作,所以后续的参数我们都不解析了 [AUTO-TRANSLATED:8aa1db56]
// Disconnect operation, so we don't parse subsequent parameters
disconnect(stream);
return false;
});
(*_parser) << Option('c', "connect", Option::ArgNone, nullptr, false, "发起tcp connect操作", nullptr);
(*_parser) << Option('t', "time_out", Option::ArgRequired, "3",false, "连接超时间", nullptr);
(*_parser) << Option('m', "method", Option::ArgRequired, "GET",false, "HTTP方法,譬如GET、POST", nullptr);
(*_parser) << Option('p', "path", Option::ArgRequired, "/index.html",false, "HTTP url路径", nullptr);
(*_parser) << Option('C', "commit", Option::ArgNone, nullptr, false, "提交HTTP请求", nullptr);
}
~CMD_http() {}
const char *description() const override {
return "http测试客户端";
}
private:
void connect(const std::shared_ptr<ostream> &stream){
(*stream) << "connect操作" << endl;
_client->connect(splitedVal("server")[0],splitedVal("server")[1],(*this)["time_out"]);
}
void disconnect(const std::shared_ptr<ostream> &stream){
(*stream) << "disconnect操作" << endl;
_client->disconnect();
}
void commit(const std::shared_ptr<ostream> &stream){
(*stream) << "commit操作" << endl;
_client->commit((*this)["method"],(*this)["path"],(*this)["server"]);
}
private:
TestClient::Ptr _client;
};
int main(int argc,char *argv[]){
REGIST_CMD(http);
signal(SIGINT,[](int ){
exit(0);
});
try{
CMD_DO("http",argc,argv);
}catch (std::exception &ex){
cout << ex.what() << endl;
return 0;
}
if(GET_CMD("http")["type"] == 0){
cout << "传统模式已退出程序请尝试shell模式" << endl;
return 0;
}
GET_CMD("http").delOption("type");
//初始化环境 [AUTO-TRANSLATED:efbad911]
// Initialize environment
Logger::Instance().add(std::shared_ptr<ConsoleChannel>(new ConsoleChannel()));
Logger::Instance().setWriter(std::shared_ptr<LogWriter>(new AsyncLogWriter()));
cout << "> 欢迎进入命令模式,你可以输入\"help\"命令获取帮助" << endl;
string cmd_line;
while(cin.good()){
try{
cout << "> ";
getline(cin,cmd_line);
CMDRegister::Instance()(cmd_line);
}catch (ExitException &){
break;
}catch (std::exception &ex){
cout << ex.what() << endl;
}
}
return 0;
}