initial commit
This commit is contained in:
105
third_party/libhv/echo-servers/asio_echo.cpp
vendored
Executable file
105
third_party/libhv/echo-servers/asio_echo.cpp
vendored
Executable file
@@ -0,0 +1,105 @@
|
||||
//
|
||||
// async_tcp_echo_server.cpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
|
||||
class session {
|
||||
public:
|
||||
session(boost::asio::io_service& io_service) :
|
||||
socket_(io_service) {
|
||||
}
|
||||
|
||||
tcp::socket& socket() {
|
||||
return socket_;
|
||||
}
|
||||
|
||||
void start() {
|
||||
socket_.async_read_some(boost::asio::buffer(data_, max_length),
|
||||
boost::bind(&session::handle_read, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void handle_read(const boost::system::error_code& error,
|
||||
size_t bytes_transferred) {
|
||||
if (!error) {
|
||||
boost::asio::async_write(socket_, boost::asio::buffer(data_,
|
||||
bytes_transferred), boost::bind(&session::handle_write,
|
||||
this, boost::asio::placeholders::error));
|
||||
} else {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void handle_write(const boost::system::error_code& error) {
|
||||
if (!error) {
|
||||
socket_.async_read_some(boost::asio::buffer(data_, max_length),
|
||||
boost::bind(&session::handle_read, this,
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred));
|
||||
} else {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tcp::socket socket_;
|
||||
enum {
|
||||
max_length = 1024
|
||||
};
|
||||
char data_[max_length];
|
||||
};
|
||||
|
||||
class server {
|
||||
public:
|
||||
server(boost::asio::io_service& io_service, short port) :
|
||||
io_service_(io_service), acceptor_(io_service, tcp::endpoint(tcp::v4(),
|
||||
port)) {
|
||||
session* new_session = new session(io_service_);
|
||||
acceptor_.async_accept(new_session->socket(), boost::bind(
|
||||
&server::handle_accept, this, new_session,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
|
||||
void handle_accept(session* new_session,
|
||||
const boost::system::error_code& error) {
|
||||
if (!error) {
|
||||
new_session->start();
|
||||
new_session = new session(io_service_);
|
||||
acceptor_.async_accept(new_session->socket(), boost::bind(
|
||||
&server::handle_accept, this, new_session,
|
||||
boost::asio::placeholders::error));
|
||||
} else {
|
||||
delete new_session;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::io_service& io_service_;
|
||||
tcp::acceptor acceptor_;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: cmd port\n");
|
||||
return -10;
|
||||
}
|
||||
int port = atoi(argv[1]);
|
||||
|
||||
boost::asio::io_service io_service;
|
||||
server s(io_service, port);
|
||||
io_service.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
88
third_party/libhv/echo-servers/benchmark.sh
vendored
Executable file
88
third_party/libhv/echo-servers/benchmark.sh
vendored
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
|
||||
host=127.0.0.1
|
||||
port=2000
|
||||
connections=100
|
||||
duration=10
|
||||
threads=2
|
||||
sendbytes=1024
|
||||
|
||||
while getopts 'h:p:c:d:t:' opt
|
||||
do
|
||||
case $opt in
|
||||
h) host=$OPTARG;;
|
||||
p) port=$OPTARG;;
|
||||
c) connections=$OPTARG;;
|
||||
d) duration=$OPTARG;;
|
||||
t) threads=$OPTARG;;
|
||||
*) exit -1;;
|
||||
esac
|
||||
done
|
||||
|
||||
SCRIPT_DIR=$(cd `dirname $0`; pwd)
|
||||
cd ${SCRIPT_DIR}/..
|
||||
|
||||
killall_echo_servers() {
|
||||
#sudo killall libevent_echo libev_echo libuv_echo libhv_echo asio_echo poco_echo muduo_echo
|
||||
if [ $(ps aux | grep _echo | grep -v grep | wc -l) -gt 0 ]; then
|
||||
ps aux | grep _echo | grep -v grep | awk '{print $2}' | xargs sudo kill -9
|
||||
fi
|
||||
}
|
||||
|
||||
export LD_LIBRARY_PATH=lib:$LD_LIBRARY_PATH
|
||||
|
||||
killall_echo_servers
|
||||
|
||||
sport=$port
|
||||
|
||||
if [ -x bin/libevent_echo ]; then
|
||||
let port++
|
||||
bin/libevent_echo $port &
|
||||
echo "libevent running on port $port"
|
||||
fi
|
||||
|
||||
if [ -x bin/libev_echo ]; then
|
||||
let port++
|
||||
bin/libev_echo $port &
|
||||
echo "libev running on port $port"
|
||||
fi
|
||||
|
||||
if [ -x bin/libuv_echo ]; then
|
||||
let port++
|
||||
bin/libuv_echo $port &
|
||||
echo "libuv running on port $port"
|
||||
fi
|
||||
|
||||
if [ -x bin/libhv_echo ]; then
|
||||
let port++
|
||||
bin/libhv_echo $port &
|
||||
echo "libhv running on port $port"
|
||||
fi
|
||||
|
||||
if [ -x bin/asio_echo ]; then
|
||||
let port++
|
||||
bin/asio_echo $port &
|
||||
echo "asio running on port $port"
|
||||
fi
|
||||
|
||||
if [ -x bin/poco_echo ]; then
|
||||
let port++
|
||||
bin/poco_echo $port &
|
||||
echo "poco running on port $port"
|
||||
fi
|
||||
|
||||
if [ -x bin/muduo_echo ]; then
|
||||
let port++
|
||||
bin/muduo_echo $port &
|
||||
echo "muduo running on port $port"
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
|
||||
for ((p=$sport+1; p<=$port; ++p)); do
|
||||
echo -e "\n==============$p====================================="
|
||||
bin/pingpong_client -H $host -p $p -c $connections -d $duration -t $threads -b $sendbytes
|
||||
sleep 1
|
||||
done
|
||||
|
||||
killall_echo_servers
|
||||
38
third_party/libhv/echo-servers/build.sh
vendored
Executable file
38
third_party/libhv/echo-servers/build.sh
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR=$(cd `dirname $0`; pwd)
|
||||
ROOT_DIR=${SCRIPT_DIR}/..
|
||||
|
||||
# install libevent libev libuv asio poco
|
||||
UNAME=$(uname -a)
|
||||
case ${UNAME} in
|
||||
*Ubuntu*|*Debian*)
|
||||
sudo apt install libevent-dev libev-dev libuv1-dev libboost-dev libboost-system-dev libasio-dev libpoco-dev
|
||||
;;
|
||||
*CentOS*)
|
||||
sudo yum install libevent-devel libev-devel libuv-devel boost-devel asio-devel poco-devel
|
||||
;;
|
||||
*Darwin*)
|
||||
brew install libevent libev libuv boost asio poco
|
||||
;;
|
||||
*)
|
||||
echo 'please install libevent libev libuv boost asio poco'
|
||||
;;
|
||||
esac
|
||||
|
||||
# install muduo => https://github.com/chenshuo/muduo.git
|
||||
TEST_MUDUO=false
|
||||
if [ "$TEST_MUDUO" == "true" ]; then
|
||||
cd ${ROOT_DIR}/..
|
||||
git clone https://github.com/chenshuo/muduo.git
|
||||
cd muduo
|
||||
mkdir build && cd build
|
||||
cmake .. && make && sudo make install
|
||||
fi
|
||||
|
||||
# install libhv
|
||||
cd ${ROOT_DIR}
|
||||
make libhv && sudo make install && sudo ldconfig
|
||||
|
||||
# build echo-servers
|
||||
make echo-servers
|
||||
78
third_party/libhv/echo-servers/libev_echo.c
vendored
Executable file
78
third_party/libhv/echo-servers/libev_echo.c
vendored
Executable file
@@ -0,0 +1,78 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "ev.h"
|
||||
|
||||
#define RECV_BUFSIZE 8192
|
||||
static char recvbuf[RECV_BUFSIZE];
|
||||
|
||||
void do_recv(struct ev_loop *loop, struct ev_io *io, int revents) {
|
||||
int nread, nsend;
|
||||
nread = recv(io->fd, recvbuf, RECV_BUFSIZE, 0);
|
||||
if (nread <= 0) {
|
||||
goto error;
|
||||
}
|
||||
nsend = send(io->fd, recvbuf, nread, 0);
|
||||
if (nsend != nread) {
|
||||
goto error;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
ev_io_stop(loop, io);
|
||||
close(io->fd);
|
||||
free(io);
|
||||
}
|
||||
|
||||
void do_accept(struct ev_loop *loop, struct ev_io *listenio, int revents) {
|
||||
struct sockaddr_in peeraddr;
|
||||
socklen_t addrlen = sizeof(peeraddr);
|
||||
int connfd = accept(listenio->fd, (struct sockaddr*)&peeraddr, &addrlen);
|
||||
if (connfd <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ev_io* io = (struct ev_io*)malloc(sizeof(struct ev_io));
|
||||
ev_io_init(io, do_recv, connfd, EV_READ);
|
||||
ev_io_start(loop, io);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: cmd port\n");
|
||||
return -10;
|
||||
}
|
||||
int port = atoi(argv[1]);
|
||||
|
||||
struct sockaddr_in addr;
|
||||
int addrlen = sizeof(addr);
|
||||
memset(&addr, 0, addrlen);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (listenfd < 0) {
|
||||
return -20;
|
||||
}
|
||||
if (bind(listenfd, (struct sockaddr*)&addr, addrlen) < 0) {
|
||||
return -30;
|
||||
}
|
||||
if (listen(listenfd, SOMAXCONN) < 0) {
|
||||
return -40;
|
||||
}
|
||||
|
||||
struct ev_loop* loop = ev_loop_new(0);
|
||||
|
||||
struct ev_io listenio;
|
||||
ev_io_init(&listenio, do_accept, listenfd, EV_READ);
|
||||
ev_io_start(loop, &listenio);
|
||||
|
||||
ev_run(loop, 0);
|
||||
ev_loop_destroy(loop);
|
||||
return 0;
|
||||
}
|
||||
61
third_party/libhv/echo-servers/libevent_echo.c
vendored
Executable file
61
third_party/libhv/echo-servers/libevent_echo.c
vendored
Executable file
@@ -0,0 +1,61 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "event2/event.h"
|
||||
#include "event2/listener.h"
|
||||
#include "event2/bufferevent.h"
|
||||
#include "event2/buffer.h"
|
||||
|
||||
//#define RECV_BUFSIZE 8192
|
||||
|
||||
void error_cb(struct bufferevent* bev, short event, void* userdata) {
|
||||
bufferevent_free(bev);
|
||||
}
|
||||
|
||||
void read_cb(struct bufferevent* bev, void* userdata) {
|
||||
//static char recvbuf[RECV_BUFSIZE];
|
||||
//int nread = bufferevent_read(bev, &recvbuf, RECV_BUFSIZE);
|
||||
//bufferevent_write(bev, recvbuf, nread);
|
||||
struct evbuffer* buf = evbuffer_new();
|
||||
int ret = bufferevent_read_buffer(bev, buf);
|
||||
if (ret == 0) {
|
||||
bufferevent_write_buffer(bev, buf);
|
||||
}
|
||||
evbuffer_free(buf);
|
||||
}
|
||||
|
||||
void on_accept(struct evconnlistener* listener, evutil_socket_t connfd, struct sockaddr* peeraddr, int addrlen, void* userdata) {
|
||||
struct event_base* loop = evconnlistener_get_base(listener);
|
||||
struct bufferevent* bev = bufferevent_socket_new(loop, connfd, BEV_OPT_CLOSE_ON_FREE);
|
||||
bufferevent_setcb(bev, read_cb, NULL, error_cb, NULL);
|
||||
bufferevent_enable(bev, EV_READ|EV_WRITE|EV_PERSIST);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: cmd port\n");
|
||||
return -10;
|
||||
}
|
||||
int port = atoi(argv[1]);
|
||||
|
||||
struct event_base* loop = event_base_new();
|
||||
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
struct evconnlistener* listener = evconnlistener_new_bind(
|
||||
loop, on_accept, NULL,
|
||||
LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,
|
||||
-1, (struct sockaddr*)&addr, sizeof(addr));
|
||||
if (listener == NULL) {
|
||||
return -20;
|
||||
}
|
||||
|
||||
event_base_dispatch(loop);
|
||||
|
||||
evconnlistener_free(listener);
|
||||
event_base_free(loop);
|
||||
return 0;
|
||||
}
|
||||
31
third_party/libhv/echo-servers/libhv_echo.c
vendored
Executable file
31
third_party/libhv/echo-servers/libhv_echo.c
vendored
Executable file
@@ -0,0 +1,31 @@
|
||||
#include "hv/hloop.h"
|
||||
|
||||
void on_close(hio_t* io) {
|
||||
}
|
||||
|
||||
void on_recv(hio_t* io, void* buf, int readbytes) {
|
||||
hio_write(io, buf, readbytes);
|
||||
}
|
||||
|
||||
void on_accept(hio_t* io) {
|
||||
hio_setcb_close(io, on_close);
|
||||
hio_setcb_read(io, on_recv);
|
||||
hio_read(io);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: cmd port\n");
|
||||
return -10;
|
||||
}
|
||||
int port = atoi(argv[1]);
|
||||
|
||||
hloop_t* loop = hloop_new(0);
|
||||
hio_t* listenio = hloop_create_tcp_server(loop, "0.0.0.0", port, on_accept);
|
||||
if (listenio == NULL) {
|
||||
return -20;
|
||||
}
|
||||
hloop_run(loop);
|
||||
hloop_free(&loop);
|
||||
return 0;
|
||||
}
|
||||
75
third_party/libhv/echo-servers/libuv_echo.c
vendored
Executable file
75
third_party/libhv/echo-servers/libuv_echo.c
vendored
Executable file
@@ -0,0 +1,75 @@
|
||||
#define _GNU_SOURCE 1
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "uv.h"
|
||||
|
||||
typedef struct {
|
||||
uv_write_t req;
|
||||
uv_buf_t buf;
|
||||
} uv_write_req_t;
|
||||
|
||||
void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
|
||||
buf->base = (char*)malloc(suggested_size);
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
void close_cb(uv_handle_t* handle) {
|
||||
free(handle);
|
||||
}
|
||||
|
||||
void write_cb(uv_write_t* req, int status) {
|
||||
uv_write_req_t* wr = (uv_write_req_t*)req;
|
||||
free(wr->buf.base);
|
||||
free(wr);
|
||||
}
|
||||
|
||||
void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
|
||||
if (nread <= 0) {
|
||||
uv_close((uv_handle_t*)stream, close_cb);
|
||||
return;
|
||||
}
|
||||
uv_write_req_t* wr = (uv_write_req_t*)malloc(sizeof(uv_write_req_t));
|
||||
wr->buf.base = buf->base;
|
||||
wr->buf.len = nread;
|
||||
uv_write(&wr->req, stream, &wr->buf, 1, write_cb);
|
||||
}
|
||||
|
||||
void do_accept(uv_stream_t* server, int status) {
|
||||
uv_tcp_t* tcp_stream = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
|
||||
uv_tcp_init(server->loop, tcp_stream);
|
||||
uv_accept(server, (uv_stream_t*)tcp_stream);
|
||||
uv_read_start((uv_stream_t*)tcp_stream, alloc_cb, read_cb);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: cmd port\n");
|
||||
return -10;
|
||||
}
|
||||
int port = atoi(argv[1]);
|
||||
|
||||
uv_loop_t loop;
|
||||
uv_loop_init(&loop);
|
||||
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
//addr.sin_family = AF_INET;
|
||||
//addr.sin_port = htons(port);
|
||||
uv_ip4_addr("0.0.0.0", port, &addr);
|
||||
|
||||
uv_tcp_t tcp_server;
|
||||
uv_tcp_init(&loop, &tcp_server);
|
||||
int ret = uv_tcp_bind(&tcp_server, (struct sockaddr*)&addr, 0);
|
||||
if (ret) {
|
||||
return -20;
|
||||
}
|
||||
ret = uv_listen((uv_stream_t*)&tcp_server, SOMAXCONN, do_accept);
|
||||
if (ret) {
|
||||
return -30;
|
||||
}
|
||||
|
||||
uv_run(&loop, UV_RUN_DEFAULT);
|
||||
return 0;
|
||||
}
|
||||
62
third_party/libhv/echo-servers/muduo_echo.cpp
vendored
Executable file
62
third_party/libhv/echo-servers/muduo_echo.cpp
vendored
Executable file
@@ -0,0 +1,62 @@
|
||||
// @see muduo/examples/simple/echo
|
||||
#include "muduo/base/Logging.h"
|
||||
#include "muduo/net/EventLoop.h"
|
||||
#include "muduo/net/InetAddress.h"
|
||||
#include "muduo/net/TcpServer.h"
|
||||
|
||||
using std::placeholders::_1;
|
||||
using std::placeholders::_2;
|
||||
using std::placeholders::_3;
|
||||
|
||||
using muduo::Timestamp;
|
||||
|
||||
using muduo::net::EventLoop;
|
||||
using muduo::net::InetAddress;
|
||||
using muduo::net::TcpServer;
|
||||
using muduo::net::TcpConnectionPtr;
|
||||
using muduo::net::Buffer;
|
||||
|
||||
class EchoTcpServer {
|
||||
public:
|
||||
EchoTcpServer(EventLoop* loop, const InetAddress& addr)
|
||||
: server_(loop, addr, "EchoTcpServer")
|
||||
{
|
||||
server_.setConnectionCallback(std::bind(&EchoTcpServer::onConnection, this, _1));
|
||||
server_.setMessageCallback(std::bind(&EchoTcpServer::onMessage, this, _1, _2, _3));
|
||||
}
|
||||
|
||||
void start() {
|
||||
server_.start();
|
||||
}
|
||||
|
||||
private:
|
||||
void onConnection(const TcpConnectionPtr& conn) {
|
||||
}
|
||||
|
||||
void onMessage(const TcpConnectionPtr& conn,
|
||||
Buffer* buf, Timestamp time) {
|
||||
muduo::string msg(buf->retrieveAllAsString());
|
||||
conn->send(msg);
|
||||
}
|
||||
|
||||
TcpServer server_;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: cmd port\n");
|
||||
return -10;
|
||||
}
|
||||
int port = atoi(argv[1]);
|
||||
|
||||
muduo::g_logLevel = muduo::Logger::ERROR;
|
||||
muduo::net::EventLoop loop;
|
||||
|
||||
muduo::net::InetAddress addr(port);
|
||||
EchoTcpServer server(&loop, addr);
|
||||
server.start();
|
||||
|
||||
loop.loop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
143
third_party/libhv/echo-servers/pingpong_client.cpp
vendored
Executable file
143
third_party/libhv/echo-servers/pingpong_client.cpp
vendored
Executable file
@@ -0,0 +1,143 @@
|
||||
#include "hv/hmain.h" // import parse_opt
|
||||
#include "hv/hloop.h"
|
||||
#include "hv/hsocket.h"
|
||||
|
||||
#include "hv/EventLoopThreadPool.h"
|
||||
using namespace hv;
|
||||
|
||||
static const char options[] = "hvH:p:c:d:t:b:";
|
||||
|
||||
static const char detail_options[] = R"(
|
||||
-h Print help infomation
|
||||
-v Show verbose infomation
|
||||
-H <Host> default 127.0.0.1
|
||||
-p <port>
|
||||
-c <connections> Number of connections, default: 1000
|
||||
-d <duration> Duration of test, default: 10s
|
||||
-t <threads> Number of threads, default: 4
|
||||
-b <bytes> Bytes of send buffer, default: 4096
|
||||
)";
|
||||
|
||||
static int connections = 1000;
|
||||
static int duration = 10;
|
||||
static int threads = 4;
|
||||
|
||||
static bool verbose = false;
|
||||
static const char* host = "127.0.0.1";
|
||||
static int port = 0;
|
||||
static int sendbytes = 4096;
|
||||
static void* sendbuf = NULL;
|
||||
|
||||
static std::atomic<int> connected_num(0);
|
||||
static std::atomic<int> disconnected_num(0);
|
||||
static std::atomic<uint64_t> total_readcount(0);
|
||||
static std::atomic<uint64_t> total_readbytes(0);
|
||||
|
||||
static void print_help() {
|
||||
printf("Usage: %s [%s]\n", g_main_ctx.program_name, options);
|
||||
printf("Options:\n%s\n", detail_options);
|
||||
}
|
||||
|
||||
static void print_cmd() {
|
||||
printf("Running %ds test @ %s:%d\n", duration, host, port);
|
||||
printf("%d threads and %d connections, send %d bytes each time\n", threads, connections, sendbytes);
|
||||
}
|
||||
|
||||
static void print_result() {
|
||||
printf("total readcount=%llu readbytes=%llu\n",
|
||||
(unsigned long long)total_readcount,
|
||||
(unsigned long long)total_readbytes);
|
||||
printf("throughput = %llu MB/s\n", (total_readbytes) / ((unsigned long long)duration * 1024 * 1024));
|
||||
}
|
||||
|
||||
static void on_close(hio_t* io) {
|
||||
if (++disconnected_num == connections) {
|
||||
if (verbose) {
|
||||
printf("all disconnected\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void on_recv(hio_t* io, void* buf, int readbytes) {
|
||||
++total_readcount;
|
||||
total_readbytes += readbytes;
|
||||
hio_write(io, buf, readbytes);
|
||||
}
|
||||
|
||||
static void on_connect(hio_t* io) {
|
||||
if (++connected_num == connections) {
|
||||
if (verbose) {
|
||||
printf("all connected\n");
|
||||
}
|
||||
}
|
||||
|
||||
hio_write(io, sendbuf, sendbytes);
|
||||
|
||||
hio_setcb_read(io, on_recv);
|
||||
hio_read_start(io);
|
||||
}
|
||||
|
||||
static void start_connect(hloop_t* loop) {
|
||||
hio_t* io = hio_create_socket(loop, host, port, HIO_TYPE_TCP, HIO_CLIENT_SIDE);
|
||||
if (io == NULL) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
tcp_nodelay(hio_fd(io), 1);
|
||||
hio_setcb_connect(io, on_connect);
|
||||
hio_setcb_close(io, on_close);
|
||||
hio_connect(io);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// parse cmdline
|
||||
main_ctx_init(argc, argv);
|
||||
int ret = parse_opt(argc, argv, options);
|
||||
if (ret != 0) {
|
||||
print_help();
|
||||
exit(ret);
|
||||
}
|
||||
const char* strHost = get_arg("H");
|
||||
const char* strPort = get_arg("p");
|
||||
const char* strConnections = get_arg("c");
|
||||
const char* strDuration = get_arg("d");
|
||||
const char* strThreads = get_arg("t");
|
||||
const char* strBytes = get_arg("b");
|
||||
|
||||
if (strHost) host = strHost;
|
||||
if (strPort) port = atoi(strPort);
|
||||
if (strConnections) connections = atoi(strConnections);
|
||||
if (strDuration) duration = atoi(strDuration);
|
||||
if (strThreads) threads = atoi(strThreads);
|
||||
if (strBytes) sendbytes = atoi(strBytes);
|
||||
|
||||
if (get_arg("h") || port == 0) {
|
||||
print_help();
|
||||
exit(0);
|
||||
}
|
||||
if (get_arg("v")) {
|
||||
verbose = true;
|
||||
}
|
||||
sendbuf = malloc(sendbytes);
|
||||
|
||||
print_cmd();
|
||||
|
||||
EventLoopThreadPool loop_threads(threads);
|
||||
loop_threads.start(true);
|
||||
for (int i = 0; i < connections; ++i) {
|
||||
EventLoopPtr loop = loop_threads.nextLoop();
|
||||
loop->runInLoop(std::bind(start_connect, loop->loop()));
|
||||
}
|
||||
|
||||
// stop after seconds
|
||||
loop_threads.loop()->setTimeout(duration * 1000, [&loop_threads](TimerID timerID){
|
||||
loop_threads.stop(false);
|
||||
});
|
||||
|
||||
// wait loop_threads exit
|
||||
loop_threads.join();
|
||||
|
||||
print_result();
|
||||
|
||||
return 0;
|
||||
}
|
||||
225
third_party/libhv/echo-servers/poco_echo.cpp
vendored
Executable file
225
third_party/libhv/echo-servers/poco_echo.cpp
vendored
Executable file
@@ -0,0 +1,225 @@
|
||||
//
|
||||
// EchoServer.cpp
|
||||
//
|
||||
// $Id: //poco/1.3/Net/samples/EchoServer/src/EchoServer.cpp#1 $
|
||||
//
|
||||
// This sample demonstrates the SocketReactor and SocketAcceptor classes.
|
||||
//
|
||||
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Net/SocketReactor.h"
|
||||
#include "Poco/Net/SocketAcceptor.h"
|
||||
#include "Poco/Net/SocketNotification.h"
|
||||
#include "Poco/Net/StreamSocket.h"
|
||||
#include "Poco/Net/ServerSocket.h"
|
||||
#include "Poco/NObserver.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/Util/ServerApplication.h"
|
||||
#include "Poco/Util/Option.h"
|
||||
#include "Poco/Util/OptionSet.h"
|
||||
#include "Poco/Util/HelpFormatter.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
using Poco::Net::SocketReactor;
|
||||
using Poco::Net::SocketAcceptor;
|
||||
using Poco::Net::ReadableNotification;
|
||||
using Poco::Net::ShutdownNotification;
|
||||
using Poco::Net::ServerSocket;
|
||||
using Poco::Net::StreamSocket;
|
||||
using Poco::NObserver;
|
||||
using Poco::AutoPtr;
|
||||
using Poco::Thread;
|
||||
using Poco::Util::ServerApplication;
|
||||
using Poco::Util::Application;
|
||||
using Poco::Util::Option;
|
||||
using Poco::Util::OptionSet;
|
||||
using Poco::Util::HelpFormatter;
|
||||
|
||||
|
||||
class EchoServiceHandler
|
||||
{
|
||||
public:
|
||||
EchoServiceHandler(StreamSocket& socket, SocketReactor& reactor):
|
||||
_socket(socket),
|
||||
_reactor(reactor),
|
||||
_pBuffer(new char[BUFFER_SIZE])
|
||||
{
|
||||
// Application& app = Application::instance();
|
||||
// app.logger().information("Connection from " + socket.peerAddress().toString());
|
||||
|
||||
_reactor.addEventHandler(_socket, NObserver<EchoServiceHandler, ReadableNotification>(*this, &EchoServiceHandler::onReadable));
|
||||
_reactor.addEventHandler(_socket, NObserver<EchoServiceHandler, ShutdownNotification>(*this, &EchoServiceHandler::onShutdown));
|
||||
}
|
||||
|
||||
~EchoServiceHandler()
|
||||
{
|
||||
// Application& app = Application::instance();
|
||||
// app.logger().information("Disconnecting " + _socket.peerAddress().toString());
|
||||
|
||||
_reactor.removeEventHandler(_socket, NObserver<EchoServiceHandler, ReadableNotification>(*this, &EchoServiceHandler::onReadable));
|
||||
_reactor.removeEventHandler(_socket, NObserver<EchoServiceHandler, ShutdownNotification>(*this, &EchoServiceHandler::onShutdown));
|
||||
delete [] _pBuffer;
|
||||
}
|
||||
|
||||
void onReadable(const AutoPtr<ReadableNotification>& pNf)
|
||||
{
|
||||
int n = _socket.receiveBytes(_pBuffer, BUFFER_SIZE);
|
||||
if (n > 0)
|
||||
_socket.sendBytes(_pBuffer, n);
|
||||
else
|
||||
delete this;
|
||||
}
|
||||
|
||||
void onShutdown(const AutoPtr<ShutdownNotification>& pNf)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
BUFFER_SIZE = 1024
|
||||
};
|
||||
|
||||
StreamSocket _socket;
|
||||
SocketReactor& _reactor;
|
||||
char* _pBuffer;
|
||||
};
|
||||
|
||||
|
||||
class EchoServer: public Poco::Util::ServerApplication
|
||||
/// The main application class.
|
||||
///
|
||||
/// This class handles command-line arguments and
|
||||
/// configuration files.
|
||||
/// Start the EchoServer executable with the help
|
||||
/// option (/help on Windows, --help on Unix) for
|
||||
/// the available command line options.
|
||||
///
|
||||
/// To use the sample configuration file (EchoServer.properties),
|
||||
/// copy the file to the directory where the EchoServer executable
|
||||
/// resides. If you start the debug version of the EchoServer
|
||||
/// (EchoServerd[.exe]), you must also create a copy of the configuration
|
||||
/// file named EchoServerd.properties. In the configuration file, you
|
||||
/// can specify the port on which the server is listening (default
|
||||
/// 9977) and the format of the date/time string sent back to the client.
|
||||
///
|
||||
/// To test the EchoServer you can use any telnet client (telnet localhost 9977).
|
||||
{
|
||||
public:
|
||||
EchoServer(): _helpRequested(false)
|
||||
{
|
||||
}
|
||||
|
||||
~EchoServer()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void initialize(Application& self)
|
||||
{
|
||||
loadConfiguration(); // load default configuration files, if present
|
||||
ServerApplication::initialize(self);
|
||||
}
|
||||
|
||||
void uninitialize()
|
||||
{
|
||||
ServerApplication::uninitialize();
|
||||
}
|
||||
|
||||
void defineOptions(OptionSet& options)
|
||||
{
|
||||
ServerApplication::defineOptions(options);
|
||||
|
||||
options.addOption(
|
||||
Option("help", "h", "display help information on command line arguments")
|
||||
.required(false)
|
||||
.repeatable(false));
|
||||
}
|
||||
|
||||
void handleOption(const std::string& name, const std::string& value)
|
||||
{
|
||||
ServerApplication::handleOption(name, value);
|
||||
|
||||
if (name == "help")
|
||||
_helpRequested = true;
|
||||
}
|
||||
|
||||
void displayHelp()
|
||||
{
|
||||
HelpFormatter helpFormatter(options());
|
||||
helpFormatter.setCommand(commandName());
|
||||
helpFormatter.setUsage("OPTIONS");
|
||||
helpFormatter.setHeader("An echo server implemented using the Reactor and Acceptor patterns.");
|
||||
helpFormatter.format(std::cout);
|
||||
}
|
||||
|
||||
int main(const std::vector<std::string>& args)
|
||||
{
|
||||
if (_helpRequested)
|
||||
{
|
||||
displayHelp();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.size() < 1) {
|
||||
printf("Usage: cmd port\n");
|
||||
return -10;
|
||||
}
|
||||
int port = atoi(args[0].c_str());
|
||||
// set-up a server socket
|
||||
ServerSocket svs(port);
|
||||
// set-up a SocketReactor...
|
||||
SocketReactor reactor;
|
||||
// ... and a SocketAcceptor
|
||||
SocketAcceptor<EchoServiceHandler> acceptor(svs, reactor);
|
||||
// run the reactor in its own thread so that we can wait for
|
||||
// a termination request
|
||||
Thread thread;
|
||||
thread.start(reactor);
|
||||
// wait for CTRL-C or kill
|
||||
waitForTerminationRequest();
|
||||
// Stop the SocketReactor
|
||||
reactor.stop();
|
||||
thread.join();
|
||||
}
|
||||
return Application::EXIT_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _helpRequested;
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
EchoServer app;
|
||||
return app.run(argc, argv);
|
||||
}
|
||||
Reference in New Issue
Block a user