Created
January 6, 2017 09:33
-
-
Save yjhjstz/ee1820efe0ff0c1ed83a6eb4649c7985 to your computer and use it in GitHub Desktop.
pingpong-client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <boost/thread.hpp> | |
#include <boost/asio.hpp> | |
#include <memory> | |
#include <atomic> | |
#include <chrono> | |
#include <sys/resource.h> | |
using namespace boost::asio; | |
using namespace boost::asio::ip; | |
using namespace std::chrono; | |
using boost::system::error_code; | |
using std::shared_ptr; | |
// 由于socket的析构要依赖于io_service, 所以注意控制 | |
// io_service的生命期要长于socket | |
io_service ios; | |
tcp::endpoint addr(address::from_string("127.0.0.1"), 43333); | |
const int g_buflen = 4096; | |
std::atomic<long long unsigned> g_sendbytes{0}, g_recvbytes{0}, g_qps{0}; | |
std::atomic<int> session_count{0}; | |
uint32_t qdata = 4; | |
int thread_count = 4; | |
int conn_count = 1024; | |
void on_err(shared_ptr<tcp::socket> s, char* buf) | |
{ | |
delete buf; | |
} | |
void async_read(shared_ptr<tcp::socket> s, char* buf); | |
void async_write(shared_ptr<tcp::socket> s, char* buf) | |
{ | |
s->async_write_some(buffer(buf, qdata), [s, buf](error_code const& ec, size_t n) { | |
if (ec) { | |
on_err(s, buf); | |
return ; | |
} | |
g_sendbytes += n; | |
async_read(s, buf); | |
}); | |
} | |
void async_read(shared_ptr<tcp::socket> s, char* buf) | |
{ | |
s->async_read_some(buffer(buf, g_buflen), [s, buf](error_code const& ec, size_t n) { | |
if (ec) { | |
on_err(s, buf); | |
--session_count; | |
return ; | |
} | |
g_recvbytes += n; | |
async_write(s, buf); | |
}); | |
} | |
void on_connected(error_code ec, shared_ptr<tcp::socket> s) | |
{ | |
++session_count; | |
char *writebuf = new char[g_buflen]; | |
// char *recvbuf = new char[g_buflen]; | |
async_write(s, writebuf); | |
// async_read(s, recvbuf); | |
} | |
void connect(shared_ptr<tcp::socket> s) | |
{ | |
s->async_connect(addr, std::bind(&on_connected, std::placeholders::_1, s)); | |
} | |
void echo_client() | |
{ | |
shared_ptr<tcp::socket> s(new tcp::socket(ios)); | |
connect(s); | |
} | |
void show_status() | |
{ | |
static int show_title = 0; | |
static long long unsigned last_sendbytes = 0, last_recvbytes = 0; | |
static auto start_time = system_clock::now(); | |
static auto last_time = system_clock::now(); | |
auto now = system_clock::now(); | |
if (show_title++ % 10 == 0) { | |
printf("thread:%d, qdata:%d\n", thread_count, qdata); | |
printf(" conn send(KB) recv(KB) qps AverageQps time_delta(ms)\n"); | |
} | |
printf("%6d %9llu %9llu %7d %7d %7d\n", | |
(int)session_count, (g_sendbytes - last_sendbytes) / 1024, (g_recvbytes - last_recvbytes) / 1024, | |
(int)(double)(g_recvbytes - last_recvbytes) / qdata, | |
(int)((double)g_recvbytes / qdata / std::max<int>(1, duration_cast<seconds>(now - start_time).count() + 1)), | |
(int)duration_cast<milliseconds>(now - last_time).count() | |
); | |
last_time = now; | |
last_sendbytes = g_sendbytes; | |
last_recvbytes = g_recvbytes; | |
} | |
int main(int argc, char **argv) | |
{ | |
if (argc > 1) | |
if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { | |
printf("\n Usage: %s [ThreadCount] [Connection_Count] [QueryDataLength]\n", argv[0]); | |
printf("\n Default: %s %d 1024 4\n", argv[0], thread_count); | |
printf("\n For example:\n %s 2 1000 32\n", argv[0]); | |
printf("\n That's means: start client with 2 threads, create 1000 tcp connection to server, and per data-package is 32 bytes.\n\n"); | |
exit(1); | |
} | |
if (argc > 1) | |
thread_count = atoi(argv[1]); | |
if (argc > 2) | |
conn_count = atoi(argv[2]); | |
if (argc > 3) | |
qdata = atoi(argv[3]); | |
rlimit of = {65536, 65536}; | |
if (-1 == setrlimit(RLIMIT_NOFILE, &of)) { | |
perror("setrlimit"); | |
exit(1); | |
} | |
for (int i = 0; i < conn_count; ++i) | |
echo_client(); | |
boost::thread_group tg; | |
for (int i = 0; i < thread_count; ++i) | |
tg.create_thread([]{ ios.run(); }); | |
for (;;) { | |
sleep(1); | |
show_status(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment