Skip to content
Merged

Tg #17

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions example/chat_server_demo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/** @file
*
* @ingroup example_module
*
* @brief Example of TCP multichat server network program.
*
* @author Thurman Gillespy
*
* Copyright (c) 2019 Thurman Gillespy
* 4/15/19
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
* Sample make file:
g++ -std=c++17 -Wall -Werror \
-I ../include \
-I ~/Projects/utility-rack/include/ \
-I ~/Projects/asio/asio/include/ \
-I ~/Projects/boost_1_69_0/ \
chat_server_demo.cpp -lpthread -o chat_server
*
*/

#include <iostream>
#include <cstdlib> // EXIT_SUCCESS
#include <cstddef> // std::size_t
#include <string>
#include <chrono>
#include <thread>
#include <utility> // std::ref
#include <cassert>

#include "net_ip/net_ip.hpp"
#include "net_ip/basic_net_entity.hpp"
#include "net_ip/component/worker.hpp"
#include "net_ip/component/send_to_all.hpp"

using io_context = asio::io_context;
using io_interface = chops::net::tcp_io_interface;
using const_buf = asio::const_buffer;
using endpoint = asio::ip::tcp::endpoint;

// process command line args, set ip_addr, port, param as needed
bool process_args(int argc, char* const argv[], std::string& ip_addr,
std::string& port, bool& print_errors) {
const std::string PORT = "5001";
const std::string LOCAL_LOOP = "127.0.0.1";
const std::string USAGE =
"usage:\n"
" ./chat_server [-h] [-e] [port]\n"
" -h print usage\n"
" -e print all error messages to console\n"
" default port = " + PORT + "\n"
" server IP address (fixed) = " + LOCAL_LOOP + " (local loop)";

const std::string HELP = "-h";
const std::string ERR = "-e";

// set default values
ip_addr = LOCAL_LOOP;
port = PORT;

if (argc > 3 || (argc == 2 && argv[1] == HELP)) {
std::cout << USAGE << std::endl;
return EXIT_FAILURE;
}

if (argc == 2) {
if (argv[1] == ERR) {
print_errors = true;
} else {
port = argv[1];
}
}

if (argc == 3) {
if (argv[1] == ERR) {
print_errors = true;
port = argv[2];
} else {
std::cout << USAGE << std::endl;
return EXIT_FAILURE;
}
}

return EXIT_SUCCESS;
}

int main(int argc, char *argv[])
{
const std::string LOCAL = "[local] ";
const std::string SYSTEM = "[system] ";
const std::string SERVER = "[server] ";
const std::string DELIM = "\a"; // alert (bell)
std::string ip_addr;
std::string port;
bool print_errors = false;
bool finished = false;

if (process_args(argc, argv, ip_addr, port, print_errors) == EXIT_FAILURE) {
return EXIT_FAILURE;
}

// work guard - handles @c std::thread and @c asio::io_context management
chops::net::worker wk;
wk.start();

// handles all @c io_interfaces
chops::net::send_to_all<chops::net::tcp_io> sta;

/* lamda handlers */
// receive text from client, send out to others
const auto msg_hndlr = [&sta](const_buf buf, io_interface iof, endpoint ep) {
// sta.send(buf.data(), buf.size(), iof);
sta.send(buf.data(), buf.size());

return true;
};

const auto io_state_chng_hndlr = [&sta, &msg_hndlr, &DELIM]
(io_interface iof, std::size_t n, bool flag) {
// add to or remove @c io_interface from list in sta
sta(iof, n, flag);
if (flag) {
iof.start_io(DELIM, msg_hndlr);
}
};

const auto err_func = [&print_errors](io_interface iof, std::error_code err) {
if (print_errors) {
std::cerr << err << ", " << err.message() << std::endl;
}
};

// create @c net_ip instance
chops::net::net_ip server(wk.get_io_context());
// make @c tcp_acceptor, ruitn @c network_entity
auto net_entity = server.make_tcp_acceptor(port.c_str());
assert(net_entity.is_valid());
// start network entity, emplace handlers
net_entity.start(io_state_chng_hndlr, err_func);

std::cout << "chops-net-ip chat server demo" << std::endl;
std::cout << " port: " << port << std::endl;
if (print_errors) {
std::cout << " all error messages printed to console" << std::endl;
}

while (!finished) {
std::string s;
std::cout << "press return to exit" << std::endl;
getline(std::cin, s);
s = "server shutting down" + DELIM;
sta.send(s.data(), s.size());
finished = true;
}
// delay so message gets sent
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// shutdown code here?
// net_entity.stop();

wk.stop();


return EXIT_SUCCESS;
}
13 changes: 5 additions & 8 deletions example/local_echo_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ g++ -std=c++17 -Wall -Werror \
-I ~/Projects/asio/asio/include \
-I ~/Projects/boost_1_69_0/ \
local_echo_demo.cpp -lpthread -o local
*
* BUGS:
* - leaks memory like a sieve. Under investigation.
*
*/

Expand Down Expand Up @@ -126,8 +123,8 @@ int main() {
std::string s(static_cast<const char*> (buf.data()), buf.size());
auto to_upper = [] (char& c) { c = ::toupper(c); };
std::for_each(s.begin(), s.end(), to_upper);
// send c-string back over network connection
iof.send(s.c_str(), s.size() + 1);
// send uppercase string data back over network connection
iof.send(s.data(), s.size());

// return false if user entered 'quit', otherwise true
return s == "QUIT\n" ? false: true;
Expand Down Expand Up @@ -186,19 +183,19 @@ int main() {

assert(tcp_connect_iof.is_valid()); // fails without a pause

std::cout << "network demo over local loop" << std::endl;
std::cout << "network echo demo over local loop" << std::endl;
std::cout << "enter a string at the prompt" << std::endl;
std::cout << "the string will be returned in uppercase" << std::endl;
std::cout << "enter \'quit\' to exit" << std::endl << std::endl;

// get std::string from user
// send as c-string over network connection
// send string data over network connection
std::string s;
while (s != "quit\n") {
std::cout << "> ";
std::getline (std::cin, s);
s += "\n"; // needed for deliminator
// send c-string from @c tcp_connector to @c tcp_acceptor
// send string from @c tcp_connector to @c tcp_acceptor
tcp_connect_iof.send(s.data(), s.size());
// pause so returned string is displayed before next prompt
std::this_thread::sleep_for(std::chrono::milliseconds(100));
Expand Down
Loading