2019-07-27 22:44:32 +08:00
|
|
|
|
#include <iostream>
|
2015-05-18 20:05:22 +08:00
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include "lib_acl.h"
|
|
|
|
|
#include "acl_cpp/lib_acl.hpp"
|
|
|
|
|
|
|
|
|
|
static int __timeout = 10;
|
|
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
|
{
|
|
|
|
|
STATUS_T_HDR,
|
|
|
|
|
STATUS_T_DAT,
|
|
|
|
|
} status_t;
|
|
|
|
|
|
2019-07-27 22:44:32 +08:00
|
|
|
|
// 数据头
|
2015-05-18 20:05:22 +08:00
|
|
|
|
struct DAT_HDR
|
|
|
|
|
{
|
2019-07-27 22:44:32 +08:00
|
|
|
|
int len; // 数据体长度
|
|
|
|
|
char cmd[64]; // 命令字
|
2015-05-18 20:05:22 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class mythread : public acl::thread
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
mythread(const char* addr, int count, int length)
|
2019-06-16 20:10:40 +08:00
|
|
|
|
: addr_(addr)
|
|
|
|
|
, count_(count)
|
|
|
|
|
, length_(length)
|
2015-05-18 20:05:22 +08:00
|
|
|
|
{
|
|
|
|
|
req_dat_ = (char*) malloc(length);
|
|
|
|
|
res_dat_ = (char*) malloc(length);
|
|
|
|
|
res_max_ = length;
|
|
|
|
|
memset(req_dat_, 'X', length_);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-16 20:10:40 +08:00
|
|
|
|
~mythread(void)
|
2015-05-18 20:05:22 +08:00
|
|
|
|
{
|
|
|
|
|
free(req_dat_);
|
|
|
|
|
free(res_dat_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
2019-06-16 20:10:40 +08:00
|
|
|
|
// @override
|
|
|
|
|
void* run(void)
|
2015-05-18 20:05:22 +08:00
|
|
|
|
{
|
|
|
|
|
acl::socket_stream conn;
|
|
|
|
|
|
2019-07-27 22:44:32 +08:00
|
|
|
|
// 连接服务器
|
2019-06-16 20:10:40 +08:00
|
|
|
|
if (!conn.open(addr_.c_str(), __timeout, __timeout)) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
printf("connect %s error\r\n", addr_.c_str());
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-16 20:10:40 +08:00
|
|
|
|
for (int i = 0; i < count_; i++) {
|
|
|
|
|
if (!handle_pkg(conn, i)) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
break;
|
2019-06-16 20:10:40 +08:00
|
|
|
|
}
|
2015-05-18 20:05:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bool handle_pkg(acl::socket_stream& conn, int i)
|
|
|
|
|
{
|
|
|
|
|
DAT_HDR req_hdr;
|
|
|
|
|
req_hdr.len = htonl(length_);
|
|
|
|
|
ACL_SAFE_STRNCPY(req_hdr.cmd, "SEND", sizeof(req_hdr.cmd));
|
|
|
|
|
|
2019-07-27 22:44:32 +08:00
|
|
|
|
// 先写数据头
|
2019-06-16 20:10:40 +08:00
|
|
|
|
if (conn.write(&req_hdr, sizeof(req_hdr)) == -1) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
printf("write hdr to server failed\r\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-27 22:44:32 +08:00
|
|
|
|
// 再写数据体
|
2019-06-16 20:10:40 +08:00
|
|
|
|
if (conn.write(req_dat_, length_) == -1) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
printf("write dat to server failed\r\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
|
2019-07-27 22:44:32 +08:00
|
|
|
|
// 先读响应头
|
2015-05-18 20:05:22 +08:00
|
|
|
|
DAT_HDR res;
|
2019-06-16 20:10:40 +08:00
|
|
|
|
if (conn.read(&res, sizeof(DAT_HDR)) == -1) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
printf("read DAT_HDR error\r\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-27 22:44:32 +08:00
|
|
|
|
// 将响应体数据长度转为主机字节序
|
2015-05-18 20:05:22 +08:00
|
|
|
|
res.len = ntohl(res.len);
|
2019-06-16 20:10:40 +08:00
|
|
|
|
if (res.len <= 0) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
printf("invalid length: %d\r\n", res.len);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-27 22:44:32 +08:00
|
|
|
|
// 检测是否需要重新分配读响应数据的内存
|
2019-06-16 20:10:40 +08:00
|
|
|
|
if (res.len + 1 >= res_max_) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
res_max_ = res.len + 1;
|
|
|
|
|
res_dat_ = (char*) realloc(res_dat_, res_max_);
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-27 22:44:32 +08:00
|
|
|
|
// 再读响应体
|
2019-06-16 20:10:40 +08:00
|
|
|
|
if (conn.read(res_dat_, res.len) == -1) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
printf("read data error, len: %d\r\n", res.len);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res_dat_[res.len] = 0;
|
2019-06-16 20:10:40 +08:00
|
|
|
|
if (i < 10) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
printf("thread: %lu, cmd: %s, dat: %s, len: %d\r\n",
|
|
|
|
|
(unsigned long) thread_id(), res.cmd,
|
|
|
|
|
res_dat_, res.len);
|
2019-06-16 20:10:40 +08:00
|
|
|
|
}
|
2015-05-18 20:05:22 +08:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
acl::string addr_;
|
2019-06-16 20:10:40 +08:00
|
|
|
|
int count_;
|
|
|
|
|
int length_;
|
2015-05-18 20:05:22 +08:00
|
|
|
|
char* req_dat_;
|
|
|
|
|
char* res_dat_;
|
2019-06-16 20:10:40 +08:00
|
|
|
|
int res_max_;
|
2015-05-18 20:05:22 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void usage(const char* procname)
|
|
|
|
|
{
|
|
|
|
|
printf("usage: %s -h[help]\r\n"
|
|
|
|
|
" -s ip:port[default: 127.0.0.1:1900]\r\n"
|
|
|
|
|
" -t timeout[default: 10]\r\n"
|
|
|
|
|
" -n count[default: 100]\r\n"
|
|
|
|
|
" -l length[default: 1024]\r\n"
|
|
|
|
|
" -c max_threads[default: 10]\r\n",
|
|
|
|
|
procname);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
|
{
|
|
|
|
|
int ch, count = 100, max_threads = 10, length = 1024;
|
|
|
|
|
acl::string addr("127.0.0.1:1900");
|
|
|
|
|
|
2019-06-16 20:10:40 +08:00
|
|
|
|
while ((ch = getopt(argc, argv, "n:c:s:ht:l:")) > 0) {
|
|
|
|
|
switch (ch) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
case 'h':
|
|
|
|
|
usage(argv[0]);
|
2019-06-16 20:10:40 +08:00
|
|
|
|
return 0;
|
2015-05-18 20:05:22 +08:00
|
|
|
|
case 'n':
|
|
|
|
|
count = atoi(optarg);
|
|
|
|
|
break;
|
|
|
|
|
case 'c':
|
|
|
|
|
max_threads = atoi(optarg);
|
|
|
|
|
break;
|
|
|
|
|
case 's':
|
|
|
|
|
addr = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 't':
|
|
|
|
|
__timeout = atoi(optarg);
|
|
|
|
|
break;
|
|
|
|
|
case 'l':
|
|
|
|
|
length = atoi(optarg);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-16 20:10:40 +08:00
|
|
|
|
acl::acl_cpp_init();
|
2015-05-18 20:05:22 +08:00
|
|
|
|
acl::log::stdout_open(true);
|
|
|
|
|
|
|
|
|
|
std::vector<mythread*> threads;
|
2019-06-16 20:10:40 +08:00
|
|
|
|
for (int i = 0; i < max_threads; i++) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
mythread* thread = new mythread(addr, count, length);
|
|
|
|
|
thread->set_detachable(false);
|
|
|
|
|
threads.push_back(thread);
|
|
|
|
|
thread->start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (std::vector<mythread*>::iterator it = threads.begin();
|
2019-06-16 20:10:40 +08:00
|
|
|
|
it != threads.end(); ++it) {
|
|
|
|
|
if (!(*it)->wait()) {
|
2015-05-18 20:05:22 +08:00
|
|
|
|
printf("thread wait error: %s\r\n", acl::last_serror());
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete *it;
|
|
|
|
|
}
|
2019-06-16 20:10:40 +08:00
|
|
|
|
|
2015-05-18 20:05:22 +08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|