Skip to content

Commit 5c683b3

Browse files
authored
Merge pull request #13 from connectivecpp/TG
Tg
2 parents a7f76cf + 4c31057 commit 5c683b3

File tree

5 files changed

+260
-1
lines changed

5 files changed

+260
-1
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
**Describe the bug**
11+
A clear and concise description of what the bug is.
12+
13+
**To Reproduce**
14+
Steps to reproduce the behavior:
15+
16+
**Expected behavior**
17+
A clear and concise description of what you expected to happen.
18+
19+
**Screenshots**
20+
If applicable, add screenshots to help explain your problem.
21+
22+
**Desktop (please complete the following information):**
23+
- OS(es): [e.g. iOS and Ubuntu Linux]
24+
- Compiler(s) (e.g. g++ 7.3 and clang x.x)
25+
- Version [e.g. 22]
26+
27+
**Additional context**
28+
Add any other context about the problem here.

.github/ISSUE_TEMPLATE/custom.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
name: Custom issue template
3+
about: Describe this issue template's purpose here.
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: Feature request
3+
about: Suggest an idea for this project
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
**Is your feature request related to a problem? Please describe.**
11+
A clear and concise description of what the problem is.
12+
13+
**Describe the solution you'd like**
14+
A clear and concise description of what you want to happen.
15+
16+
**Describe alternatives you've considered**
17+
A clear and concise description of any alternative solutions or features you've considered.
18+
19+
**Additional context**
20+
Add any other context or screenshots about the feature request here.

example/local_chat_demo.cpp

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/** @file
2+
*
3+
* @ingroup example_module
4+
*
5+
* @brief Example of TCP send/recieve text string over local loop network
6+
* connection.
7+
*
8+
* @author Thurman Gillespy
9+
*
10+
* Copyright (c) 2019 Thurman Gillespy
11+
* 4/4/19
12+
*
13+
* Distributed under the Boost Software License, Version 1.0.
14+
* (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
15+
*
16+
* Sample make file:
17+
* g++ -std=c++17 -Wall -Werror \
18+
* -I ../include -I ../include/net_ip/ -I ~/Projects/utility-rack/include/ \
19+
* -I ~/Projects/asio/asio/include \
20+
* local_chat_demo.cpp -lpthread
21+
*
22+
* BUGS:
23+
* - leaks memory like a sieve. Under investigation.
24+
*
25+
*/
26+
27+
#include <iostream>
28+
#include <cstdlib> // EXIT_SUCCESS
29+
#include <cstddef> // std::size_t
30+
#include <string>
31+
#include <string_view>
32+
#include <chrono>
33+
#include <thread>
34+
#include <algorithm> // std::for_each
35+
#include <cassert>
36+
37+
#include "net_ip/net_ip.hpp"
38+
#include "net_ip/basic_net_entity.hpp"
39+
#include "component/worker.hpp"
40+
#include "queue/wait_queue.hpp"
41+
42+
using io_context = asio::io_context;
43+
using io_interface = chops::net::tcp_io_interface;
44+
using const_buf = asio::const_buffer;
45+
using tcp_io_interface = chops::net::tcp_io_interface;
46+
using endpoint = asio::ip::tcp::endpoint;
47+
48+
/** How to use @c chops-net-ip for a simple text send/receive network connection
49+
* over a local loop.
50+
*
51+
* 1. Write message handlers for the @c tcp_connector and @c tcp_acceptor.
52+
*
53+
* The @c tcp_connector_message_handler receives text from a @c tcp_acceptor
54+
* (in-bound messages). In this demo, the handler prints the text to stdout,
55+
*
56+
* The @c tcp_acceptor_message_handler receives the (out-bound) message from
57+
* the @c tcp-connector. In this demo, the handler converts the text to
58+
* uppercase, then returns the text over the same connection back to the
59+
* @c tcp_connector.
60+
*
61+
* In this demo, both message handlers return @c false when the user enters
62+
* @c "quit", otherwise @c true. @c "quit" shuts down both handlers and exits
63+
* the program.
64+
*
65+
* 2. Write @ io_state_change handlers for the @c tcp_connector and @c
66+
* @c tcp_acceptor.
67+
*
68+
* The @c tcp_connector @c io_state_change handler calls @c start_io on the
69+
* provided @c chops::net::tcp_io_interface. It then needs to return a copy
70+
* of the @c io_interface to main. The main copy will use the @c io_interface
71+
* to @c send the text message from the @c tcp_connector to the @c tcp_acceptor.
72+
*
73+
* The @c tcp_acceptor @c io_state_change handler only needs to call @c start_io
74+
* on the provided @c io_interface.
75+
*
76+
* 3. Create an instance of the @c chops::net::worker class, which provides
77+
* @c std::thread and @c asio::io_context management. Call @c worker::start
78+
* before the frist call to the @chops::net::ip facilities, then call
79+
* @c worker::stop when finished.
80+
*
81+
* 4. Create an instance of the @c chops::net::ip::net_ip class. The constructor
82+
* needs an @c asio:io_context, which is provided by the @c get_io_context()
83+
* method of the @c chops::net::worker instance.
84+
*
85+
* 5. Call @c ::make_tcp_connector on the @ net_ip instance, which returns a
86+
* copy of a @c tcp_connecvtor_network_entity.
87+
*
88+
* 6. Call @c ::make_tcp_acceptor on the @ net_ip instance, which returns a
89+
* copy of a @c tcp_acceptor_network_entity.
90+
*
91+
* 7. Call @c ::start() on both both @c network_entity. Each @c tcp_connector
92+
* and @c tcp_acceptor @ network_entity takes its' own @c io_state_change
93+
* handler, and each @ io_state_change handler takes its' own @c message_handler.
94+
*
95+
* 8. Call @c ::send() on the @c chops::net::tcp_io_interface instance to send
96+
* a text string over the local loop network connection.
97+
*
98+
* 9. See the example code and the header files for the signatures of the
99+
* handlers.
100+
*
101+
*/
102+
103+
const std::string PORT = "5001";
104+
105+
int main() {
106+
107+
/* lambda callbacks */
108+
// message handler for @c tcp_connector @c network_entity
109+
auto msg_hndlr_connect = [] (const_buf buf, io_interface iof, endpoint ep)
110+
{
111+
// receive data from acceptor, display to user
112+
std::string s (static_cast<const char*> (buf.data()), buf.size());
113+
std::cout << s; // s aleady has terminating '\n'
114+
115+
// return false if user entered 'quit', otherwise true
116+
return s == "QUIT\n" ? false: true;
117+
};
118+
119+
// message handler for @c tcp_acceptor @c message_handler
120+
// receive data from connector, send back to acceptor
121+
auto msg_hndlr_accept = [] (const_buf buf, io_interface iof, endpoint ep)
122+
{
123+
// copy buffer contents into string, convert to uppercase
124+
std::string s(static_cast<const char*> (buf.data()), buf.size());
125+
auto to_upper = [] (char& c) { c = ::toupper(c); };
126+
std::for_each(s.begin(), s.end(), to_upper);
127+
// send c-string back over network connection
128+
iof.send(s.c_str(), s.size() + 1);
129+
130+
// return false if user entered 'quit', otherwise true
131+
return s == "QUIT\n" ? false: true;
132+
};
133+
134+
// io state change handlers
135+
tcp_io_interface tcp_connect_iof; // used to send text data
136+
// handler for @c tcp_connector
137+
auto io_state_chng_connect = [&tcp_connect_iof, msg_hndlr_connect]
138+
(io_interface iof, std::size_t n, bool flag)
139+
{
140+
iof.start_io("\n", msg_hndlr_connect);
141+
// return iof to main
142+
tcp_connect_iof = iof;
143+
};
144+
145+
// handler for @c tcp_acceptor
146+
auto io_state_chng_accept = [msg_hndlr_accept]
147+
(io_interface iof, std::size_t n, bool flag)
148+
{
149+
iof.start_io("\n", msg_hndlr_accept);
150+
};
151+
152+
// error handler
153+
auto err_func = [] (io_interface iof, std::error_code err)
154+
{ std::cerr << "err_func: " << err << std::endl; };
155+
156+
// work guard - handles @c std::thread and @c asio::io_contect management
157+
chops::net::worker wk;
158+
wk.start();
159+
160+
// create input (acceptor) and output (connector) tcp connections
161+
chops::net::net_ip chat(wk.get_io_context());
162+
// make @ tcp_acceptor, receive @c tcp_acceptor_network_entity
163+
auto tane = chat.make_tcp_acceptor(PORT, "127.0.0.1");
164+
assert(tane.is_valid());
165+
166+
// make @c tcp_connector, receive @c tcp_connector_network_entity
167+
auto tcne = chat.make_tcp_connector(PORT, "127.0.0.1");
168+
assert(tcne.is_valid());
169+
170+
// start @c tcp_acceptor network entity, emplace handlers
171+
tane.start(io_state_chng_accept, err_func);
172+
// start @c tcp_connector network entity, emplace handlers
173+
tcne.start(io_state_chng_connect, err_func);
174+
175+
// pause to let things settle down
176+
std::this_thread::sleep_for(std::chrono::milliseconds(300));
177+
178+
assert(tcp_connect_iof.is_valid()); // fails without a pause
179+
180+
std::cout << "network demo over local loop" << std::endl;
181+
std::cout << "enter a string at the prompt" << std::endl;
182+
std::cout << "the string will be returned in uppercase" << std::endl;
183+
std::cout << "enter \'quit\' to exit" << std::endl << std::endl;
184+
185+
// get std::string from user
186+
// send as c-string over network connection
187+
std::string s;
188+
while (s != "quit\n") {
189+
std::cout << "> ";
190+
std::getline (std::cin, s);
191+
s += "\n"; // needed for deliminator
192+
// send c-string from @c tcp_connector to @c tcp_acceptor
193+
tcp_connect_iof.send(s.c_str(), s.size() + 1);
194+
// pause so returned string is displayed before next prompt
195+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
196+
}
197+
198+
wk.stop();
199+
200+
return EXIT_SUCCESS;
201+
}

include/net_ip/net_ip.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ namespace net {
108108
*
109109
* The @c net_ip class is safe for multiple threads to use concurrently.
110110
*
111-
* It should be noted, however, that race conditions are possible, specially for
111+
* It should be noted, however, that race conditions are possible, especially for
112112
* similar operations invoked between @c net_entity and @c io_interface
113113
* objects. For example, starting and stopping network entities concurrently between
114114
* separate objects or threads could cause unexpected behavior.

0 commit comments

Comments
 (0)