├── Makefile ├── networking-ts-stream.cpp ├── README.md ├── networking-ts-sync.cpp └── networking-ts-async.cpp /Makefile: -------------------------------------------------------------------------------- 1 | build: $(patsubst %.cpp,%.o,$(wildcard *.cpp)) 2 | @echo Building .cpp files 3 | 4 | run: *.o 5 | for f in $^; do ./$$f 2>&1 > $$f.output.txt ; done 6 | 7 | %.o: %.cpp 8 | @echo Building target $@ 9 | g++ --std=c++14 -I$(HOME)/git/networking-ts-impl/include/ -o $@ $< -lpthread 10 | 11 | clean: 12 | @echo Clean .o and .txt files 13 | rm -f *.o 14 | rm -f *.txt 15 | -------------------------------------------------------------------------------- /networking-ts-stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace net = std::experimental::net; 7 | using namespace std::chrono_literals; 8 | 9 | int main() 10 | { 11 | std::cout << "networking ts stream example" << std::endl; 12 | 13 | net::ip::tcp::iostream s; 14 | 15 | s.expires_after(5s); 16 | s.connect("ipecho.net", "http"); 17 | 18 | if(!s) { 19 | std::cout << "error: " << s.error().message() << std::endl; 20 | return -1; 21 | } 22 | 23 | s << "GET /plain HTTP/1.0\r\n"; 24 | s << "Host: ipecho.net\r\n"; 25 | s << "Accept: */*\r\n"; 26 | s << "Connection: close\r\n\r\n"; 27 | 28 | std::string header; 29 | while(s && std::getline(s, header) && header != "\r") 30 | std::cout << header << "\n"; 31 | 32 | std::cout << s.rdbuf(); 33 | std::cout << std::endl; 34 | } 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cpp-networking-ts 2 | Examples using experimental version of C++ networking ts 3 | 4 | The examples in this repository is based on the [talk by Michael Caisse on CppCon 2017](https://www.youtube.com/watch?v=2UC6_rfJuAw) 5 | 6 | ## Where to find information in the talk 7 | 8 | * The stream example (networking-ts-stream.cpp) is based on information starting at 4:59 in the talk 9 | * The synchronous example (networking-ts-sync.cpp) is based on information starting at 10:20 in the talk 10 | * The asynchronous example (networking-ts-async.cpp) is based on information starting at 26:57 in the talk 11 | 12 | ## Clone Networking TS draft implementation 13 | 14 | ``` 15 | cd ~ 16 | mkdir git 17 | cd git 18 | git clone https://github.com/chriskohlhoff/networking-ts-impl.git 19 | ``` 20 | 21 | ## How to build examples 22 | 23 | `make build` 24 | 25 | ## How to run examples 26 | 27 | `make run` 28 | 29 | ## How to view output from examples 30 | 31 | `cat .o.output.txt` 32 | 33 | Example: 34 | `cat networking-ts-stream.o.output.txt` 35 | 36 | ## Links 37 | 38 | * Networking TS Implementation - [https://github.com/chriskohlhoff/networking-ts-impl.git](https://github.com/chriskohlhoff/networking-ts-impl.git) 39 | * Boost Overivew - [http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/overview.html](http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/overview.html) 40 | * Boost Async Example - [http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/example/cpp11/chat/chat_client.cpp](http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/example/cpp11/chat/chat_client.cpp) 41 | -------------------------------------------------------------------------------- /networking-ts-sync.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace net = std::experimental::net; 6 | using namespace std::literals::string_literals; 7 | 8 | int main() 9 | { 10 | net::io_context io_context; 11 | net::ip::tcp::socket socket(io_context); 12 | net::ip::tcp::resolver resolver(io_context); 13 | 14 | std::cout << "networking ts sync example" << std::endl; 15 | 16 | net::connect(socket, resolver.resolve("ipecho.net", "http")); 17 | 18 | for(auto v : { "GET /plain HTTP/1.0\r\n"s 19 | , "Host: ipecho.net\n\n"s 20 | , "Accept: */*\r\n"s 21 | , "Connection: close\r\n\r\n"s } ) 22 | { 23 | net::write(socket, net::buffer(v)); 24 | } 25 | 26 | std::string header; 27 | net::read(socket, net::dynamic_buffer(header), 28 | [&header](auto ec, auto n) -> std::size_t 29 | { 30 | if(ec || 31 | ( header.size() > 3 32 | && header.compare(header.size()-4, 4, 33 | "\r\n\r\n") == 0 )) 34 | { 35 | return 0; 36 | } 37 | return 1; 38 | } 39 | ); 40 | 41 | std::cout << "header: " << header << std::endl; 42 | 43 | std::string body; 44 | std::error_code e; 45 | net::read(socket, net::dynamic_buffer(body), 46 | [](auto ec, auto n) -> std::size_t 47 | { 48 | if(ec) { return 0; } 49 | return 1; 50 | }, 51 | e 52 | ); 53 | 54 | if(e == net::error::eof){ 55 | // Connection closed by peer 56 | // http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/tutorial/tutdaytime1/src.html 57 | }else if(e){ 58 | std::cout << "body error: " << e << std::endl; 59 | } 60 | 61 | std::cout << "body: " << body << std::endl; 62 | } 63 | 64 | -------------------------------------------------------------------------------- /networking-ts-async.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace net = std::experimental::net; 8 | using namespace std::literals::string_literals; 9 | 10 | class async_downloader { 11 | public: 12 | async_downloader(net::io_context & io_c) : io_context_{io_c}, 13 | socket_{io_context_}, 14 | vdata_{"GET /plain HTTP/1.0\r\n"s, "Host: ipecho.net\n\n"s, "Accept: */*\r\n"s , "Connection: close\r\n\r\n"s }, 15 | resolver_{io_context_}, 16 | recv_data_{} 17 | { 18 | std::cout << "async_downloader constructor" << std::endl; 19 | }; 20 | 21 | void retrieve() 22 | { 23 | resolver_.async_resolve("ipecho.net", "http", [this](auto ec, auto end_point) { this->handle_resolve(ec, end_point); }); 24 | } 25 | 26 | private: 27 | net::io_context & io_context_; 28 | net::ip::tcp::socket socket_; 29 | std::deque vdata_; 30 | net::ip::tcp::resolver resolver_; 31 | std::string recv_data_; 32 | 33 | void handle_resolve(const std::error_code& ec, const net::ip::tcp::resolver::results_type& endpoints) 34 | { 35 | std::cout << "handle_resolve" << std::endl; 36 | if(ec) { 37 | std::cout << "resolve failed with message " << ec.message() << std::endl; 38 | } else { 39 | std::cout << "resolve successful" << std::endl; 40 | net::async_connect(socket_, endpoints, [this](auto ec, auto end_point) { (this->handle_connect)(ec, end_point); }); 41 | } 42 | } 43 | 44 | void handle_connect(const std::error_code& ec, const net::ip::tcp::endpoint& endpoint) 45 | { 46 | std::cout << "handle_connect" << std::endl; 47 | if(ec) { 48 | std::cout << "connect failed" << std::endl; 49 | } else { 50 | std::cout << "connect successful" << std::endl; 51 | write(); 52 | } 53 | } 54 | 55 | void write() 56 | { 57 | std::string str{vdata_.front()}; 58 | str.erase(std::remove(str.begin(), str.end(), '\r'), str.end()); 59 | str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); 60 | std::cout << "write: " << str << std::endl; 61 | 62 | net::async_write(socket_, net::buffer(vdata_.front()), [this](auto ec, auto bytes_transferred){ this->handle_write(ec, bytes_transferred); }); 63 | 64 | vdata_.pop_front(); 65 | } 66 | 67 | void handle_write(const std::error_code& ec, std::size_t bytes_transferred) 68 | { 69 | std::cout << "handle_write" << std::endl; 70 | if(ec) { 71 | std::cout << "write failed" << std::endl; 72 | } else if(vdata_.empty()) { 73 | std::cout << "write finished" << std::endl; 74 | this->read(); 75 | } else { 76 | write(); 77 | } 78 | } 79 | 80 | void read() 81 | { 82 | std::cout << "read" << std::endl; 83 | net::async_read(socket_, 84 | net::dynamic_buffer(recv_data_), 85 | net::transfer_all(), 86 | [this](auto ec, auto bytes_transferred){ this->handle_read(ec, bytes_transferred); } 87 | ); 88 | } 89 | 90 | void handle_read(const std::error_code& ec, std::size_t bytes_transferred) 91 | { 92 | std::cout << "handle_read" << std::endl; 93 | if(ec == net::error::eof){ 94 | // Connection closed by peer 95 | // http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/tutorial/tutdaytime1/src.html 96 | std::cout << "read finished" << std::endl; 97 | std::cout << recv_data_ << std::endl; 98 | } else if(ec) { 99 | std::cout << "read error: " << ec << std::endl; 100 | } else { 101 | std::cout << "read more" << std::endl; 102 | read(); 103 | } 104 | } 105 | 106 | }; 107 | 108 | 109 | int main() 110 | { 111 | std::cout << "networking ts async example" << std::endl; 112 | 113 | net::io_context io_context; 114 | 115 | async_downloader hd{io_context}; 116 | hd.retrieve(); 117 | 118 | std::cout << "io_context.run()" << std::endl; 119 | io_context.run(); 120 | std::cout << "end" << std::endl; 121 | } 122 | 123 | --------------------------------------------------------------------------------