-
-
Save fcharlie/15708a747255ea39060231afd196fe70 to your computer and use it in GitHub Desktop.
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 <asio.hpp> | |
#include <asio/ssl.hpp> | |
#include <algorithm> | |
#include <atomic> | |
#include <cstdlib> | |
#include <ctime> | |
#include <iostream> | |
#include <memory> | |
#include <thread> | |
#include <vector> | |
class ServerConnection { | |
public: | |
ServerConnection(asio::io_service &ioService, asio::ssl::context &context, | |
std::size_t messageSize) | |
: m_socket{ioService, context} | |
, m_buffer(messageSize) | |
{ | |
++s_runningConnections; | |
} | |
~ServerConnection() { --s_runningConnections; } | |
asio::ssl::stream<asio::ip::tcp::socket>::lowest_layer_type &socket() | |
{ | |
return m_socket.lowest_layer(); | |
} | |
void start(std::shared_ptr<ServerConnection> self, std::size_t messages) | |
{ | |
m_socket.async_handshake(asio::ssl::stream_base::server, | |
[=](const asio::error_code &) { asyncRead(self, messages); }); | |
} | |
static std::size_t runningConnections() { return s_runningConnections; } | |
private: | |
void asyncRead(std::shared_ptr<ServerConnection> self, std::size_t messages) | |
{ | |
asio::async_read(m_socket, asio::buffer(m_buffer), | |
[=](const asio::error_code &, std::size_t) { | |
if (messages > 1) | |
asyncRead(self, messages - 1); | |
}); | |
} | |
static std::atomic<std::size_t> s_runningConnections; | |
asio::ssl::stream<asio::ip::tcp::socket> m_socket; | |
std::vector<char> m_buffer; | |
}; | |
std::atomic<std::size_t> ServerConnection::s_runningConnections{0}; | |
class Server { | |
public: | |
Server(asio::io_service &ioService, std::size_t connections, | |
std::size_t messages, std::size_t messageSize) | |
: m_ioService{ioService} | |
, m_messages{messages} | |
, m_messageSize{messageSize} | |
{ | |
m_context.use_certificate_chain_file("server.pem"); | |
m_context.use_private_key_file("server.key", asio::ssl::context::pem); | |
asyncAccept(connections); | |
} | |
private: | |
void asyncAccept(std::size_t connections) | |
{ | |
auto conn = std::make_shared<ServerConnection>( | |
m_ioService, m_context, m_messageSize); | |
m_acceptor.async_accept(conn->socket(), [=](const asio::error_code &) { | |
conn->start(conn, m_messages); | |
if (connections > 1) | |
asyncAccept(connections - 1); | |
}); | |
} | |
asio::io_service &m_ioService; | |
std::size_t m_messages; | |
std::size_t m_messageSize; | |
asio::ssl::context m_context{asio::ssl::context::tlsv12_server}; | |
asio::ip::tcp::acceptor m_acceptor{ | |
m_ioService, {asio::ip::tcp::v4(), 5555}}; | |
}; | |
class ClientConnection { | |
public: | |
ClientConnection(asio::io_service &ioService, | |
asio::ip::tcp::resolver::iterator iterator, std::size_t messageSize) | |
: m_socket{ioService, m_context} | |
, m_buffer(messageSize) | |
{ | |
asio::connect(m_socket.lowest_layer(), iterator); | |
m_socket.handshake(asio::ssl::stream_base::client); | |
} | |
void asyncSend(std::size_t messages) | |
{ | |
asio::async_write(m_socket, asio::buffer(m_buffer), | |
[=](const asio::error_code &, std::size_t) { | |
if (messages > 1) | |
asyncSend(messages - 1); | |
}); | |
} | |
private: | |
asio::ssl::context m_context{asio::ssl::context::tlsv12_client}; | |
asio::ssl::stream<asio::ip::tcp::socket> m_socket; | |
std::vector<char> m_buffer; | |
}; | |
std::vector<std::thread> createThreads( | |
asio::io_service &ioService, std::size_t number) | |
{ | |
std::vector<std::thread> threads; | |
std::generate_n(std::back_inserter(threads), number, | |
[&] { return std::thread{[&] { ioService.run(); }}; }); | |
return threads; | |
} | |
std::vector<std::shared_ptr<ClientConnection>> createClients( | |
asio::io_service &ioService, std::size_t messageSize, std::size_t number) | |
{ | |
asio::ip::tcp::resolver resolver{ioService}; | |
auto iterator = resolver.resolve({"127.0.0.1", "5555"}); | |
std::vector<std::shared_ptr<ClientConnection>> clients; | |
std::generate_n(std::back_inserter(clients), number, [&] { | |
return std::make_shared<ClientConnection>( | |
ioService, iterator, messageSize); | |
}); | |
return clients; | |
} | |
std::chrono::milliseconds measureTransferTime( | |
std::vector<std::shared_ptr<ClientConnection>> &clients, | |
std::size_t messages) | |
{ | |
auto startTime = std::chrono::steady_clock::now(); | |
for (auto &client : clients) | |
client->asyncSend(messages); | |
while (ServerConnection::runningConnections() != 0) | |
std::this_thread::sleep_for(std::chrono::milliseconds{10}); | |
auto stopTime = std::chrono::steady_clock::now(); | |
return std::chrono::duration_cast<std::chrono::milliseconds>( | |
stopTime - startTime); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
if (argc < 5) { | |
std::cout << "Usage: " << argv[0] | |
<< " threads connections messages messageSize" << std::endl; | |
return 1; | |
} | |
std::size_t threadsNo = std::atoll(argv[1]); | |
std::size_t connections = std::atoll(argv[2]); | |
std::size_t messages = std::atoll(argv[3]); | |
std::size_t messageSize = std::atoll(argv[4]); | |
asio::io_service ioService; | |
asio::io_service::work idleWork{ioService}; | |
auto threads = createThreads(ioService, threadsNo); | |
Server server{ioService, connections, messages, messageSize}; | |
auto clients = createClients(ioService, messageSize, connections); | |
auto duration = measureTransferTime(clients, messages); | |
auto seconds = static_cast<double>(duration.count()) / 1000; | |
auto megabytes = | |
static_cast<double>(connections * messages * messageSize) / 1024 / 1024; | |
std::cout << megabytes << " megabytes sent and received in " << seconds | |
<< " seconds. (" << (megabytes / seconds) << " MB/s)" | |
<< std::endl; | |
ioService.stop(); | |
for (auto &thread : threads) | |
thread.join(); | |
return 0; | |
} |
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
-----BEGIN PRIVATE KEY----- | |
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAL3LACAeyeApIr3L | |
n88mv087ycqLG/DmAWC6I0fp1HD3ltC6IuAHHhp4WJhrfgJmXJJeAGZdg+X6GpCa | |
LAWngWLBOg6NvMdfOiKOOQhF88M9vwfmeOgCfsOjNFUtmwOe1N+r4eqKdQuVNdHg | |
k0ONsb8m8Mq1fz77hetRG/9YGEhrAgMBAAECgYEAirVHNTJrRgmqW13rQQFHhkfi | |
9cVvOUNQNHo1eMRbP+ijb47qGCL7jEryLQs6f9SByXMsBaRI1pZQPeh/Te6a7uet | |
TPpqlN/Z9j5W7OxYOb90jpqlRU9nHYlmEMVO4KvlRaevWz735ST17xCWuH4WbVX5 | |
dmElt1ybTjjPdEslndECQQDuWZKjx4FSVc2m8R9fGquQJI2LYgH0/U5vyVzh3MkT | |
bx5N+SbOGnsafAl628mLVp/221qhKq/IR7NyVG7WezdpAkEAy9jtpx5MfRBs/wbm | |
SAbDaeePdL1lEt/8fxYarq1ga0PL/3SxH5hl1YBdC09+N3JAenwGKIBG8okJI9dq | |
prT6swJAXGqovA5IK2ePlNJbaqHJsdsqcsfuoFJzTk7ST9UutfVY17zqefG0l8FO | |
X6/GxtswrSPCUUle3RZIEuWAEHO4OQJAVWWAUdV4l6AM+V2rlRr4PGKcj3xUXm7l | |
OVxKO0k4rlcNm+wH08OlTabj07wulQ3RAz732Xm7vxk3cgNpk4MXzwJBALHeBfTR | |
EqYLdHIDKhBrm2EuFFAoQIxJbfZCb/u3ozSJWoBgYo5VebJArXqojlvCu0nxXKb6 | |
n826OagnAPUcYn4= | |
-----END PRIVATE KEY----- |
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
-----BEGIN CERTIFICATE----- | |
MIICsTCCAhqgAwIBAgIJAJThyYbbS2KwMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNV | |
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX | |
aWRnaXRzIFB0eSBMdGQxDDAKBgNVBAMMA29tZzAeFw0xNTA0MjYxMjA2MTRaFw0x | |
NTA1MjYxMjA2MTRaMFMxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRl | |
MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDDAKBgNVBAMMA29t | |
ZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvcsAIB7J4Ckivcufzya/TzvJ | |
yosb8OYBYLojR+nUcPeW0Loi4AceGnhYmGt+AmZckl4AZl2D5foakJosBaeBYsE6 | |
Do28x186Io45CEXzwz2/B+Z46AJ+w6M0VS2bA57U36vh6op1C5U10eCTQ42xvybw | |
yrV/PvuF61Eb/1gYSGsCAwEAAaOBjDCBiTA5BgNVHR8EMjAwMC6gLKAqhihodHRw | |
Oi8vc3R1ZGVudC5hZ2guZWR1LnBsL356ZW1lay9jcmwucGVtMB0GA1UdDgQWBBQD | |
w/MdQampMXELP0eFTHq8HR9TmzAfBgNVHSMEGDAWgBQDw/MdQampMXELP0eFTHq8 | |
HR9TmzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAG/G0wF8eqBicaS5 | |
8/pyPVcdQXwl89QF84zayGKQs3KynrORiDDH1WHQOzY4C2PzAX4KoOm/tNJ+K10v | |
QWyFMS+ZeHZEwuwbK4AVlt2qMabze1OrW+7KFZnpyWAQd2GXVIMvjlYgZtfTWFIG | |
UF0yj8RNyI2GTIthCrqzHgRXYFvA | |
-----END CERTIFICATE----- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment