首页 > 代码库 > 10 C++ Boost ASIO网路通信库 TCP/UDP,HTTP
10 C++ Boost ASIO网路通信库 TCP/UDP,HTTP
tcp 同步服务器,显示服务器端时间 tcp 同步服务器,提供多种选择 多线程的tcp 同步服务器 tcp 同步客户端 boost 域名地址解析 tcp异步服务器 tcp 异步客户端 UDP同步服务器 UDP同步客户端 UDP异步服务器 UDP异步客户端 HTTP同步客户端 HTTP异步客户端 同步实验: 异步实验 多线程异步实验
tcp 同步服务器,显示服务器端时间
chunli@Linux:~/boost$ cat main.cpp #include <ctime> #include <iostream> #include <string> #include <boost/asio.hpp> using boost::asio::ip::tcp; std::string make_daytime_string() { using namespace std; // For time_t, time and ctime; time_t now = time(0); return ctime(&now); } int main() { try { boost::asio::io_service io_service; tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 8080)); for (;;) { tcp::socket socket(io_service); acceptor.accept(socket); std::string message = make_daytime_string(); boost::system::error_code ignored_error; boost::asio::write(socket, boost::asio::buffer(message), ignored_error); } } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return 0; } 编译运行: chunli@Linux:~/boost$ g++ main.cpp -l boost_system && ./a.out 客户端来访问: chunli@Linux:~$ netstat -tnlp Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 4100/a.out tcp6 0 0 :::22 :::* LISTEN - tcp6 0 0 ::1:631 :::* LISTEN - tcp6 0 0 :::80 :::* LISTEN - chunli@Linux:~$ chunli@Linux:~$ nc 127.0.0.1 8080 Tue Dec 27 13:06:53 2016 chunli@Linux:~$ nc 127.0.0.1 8080 Tue Dec 27 13:06:55 2016 chunli@Linux:~$ nc 127.0.0.1 8080 Tue Dec 27 13:06:55 2016 chunli@Linux:~$
tcp 同步服务器,提供多种选择
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <fstream> #include <sstream> #include <string> #include <boost/asio.hpp> using namespace std; using boost::asio::ip::tcp; const char serviceList[] = " Services \n" "**************************\n" "[1] Get current time. \n" "[2] Who‘s online. \n" "[3] Get system info. \n" "**************************\n" "Please pick a service[1-3]: "; void getResult(const string& cmdPrefix, const char* outputFile, string& res) { // cmd == "w > who" string cmd(cmdPrefix + outputFile); system(cmd.c_str()); ifstream fin; fin.open(outputFile); if (fin) { ostringstream os; os << fin.rdbuf(); res = os.str(); } if (fin.is_open()) { fin.close(); } } string getServiceContent(const int& select) { string res; switch (select) { case 1: { time_t t = time(0); res = ctime(&t); break; } case 2: getResult("w > ", "who", res); break; case 3: getResult("uname -a > ", "uname", res); break; default: res = "Sorry, no such service.\n"; break; } return res; } int main() { try { boost::asio::io_service io_service; // #1 tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 8868)); // #2 while(1) { tcp::socket socket(io_service); acceptor.accept(socket); boost::system::error_code ignored_error; boost::asio::write(socket, boost::asio::buffer(serviceList),ignored_error); char selection[20]; size_t n = socket.read_some(boost::asio::buffer(selection),ignored_error); string response = getServiceContent(atoi(selection)); boost::asio::write(socket, boost::asio::buffer(response),boost::asio::transfer_all(), ignored_error); } } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return 0; } 编译运行: chunli@Linux:~/boost$ g++ main.cpp -l boost_system && ./a.out 客户端来验证: chunli@Linux:~/boost$ nc 127.0.0.1 8868 Services ************************** [1] Get current time. [2] Who‘s online. [3] Get system info. ************************** Please pick a service[1-3]: 1 Tue Dec 27 13:41:51 2016 chunli@Linux:~/boost$ nc 127.0.0.1 8868 Services ************************** [1] Get current time. [2] Who‘s online. [3] Get system info. ************************** Please pick a service[1-3]: 2 13:41:54 up 3:39, 4 users, load average: 0.07, 0.03, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT chunli pts/6 chunli-pc 10:03 1:22 3.69s 3.37s vim main.cpp chunli pts/10 chunli-pc 11:58 1:14 0.89s 0.00s sh -c w > who chunli :0 :0 12:41 ?xdm? 4:25 0.44s init --user chunli pts/0 chunli-pc 13:06 2.00s 0.33s 0.00s nc 127.0.0.1 8868 chunli@Linux:~/boost$ nc 127.0.0.1 8868 Services ************************** [1] Get current time. [2] Who‘s online. [3] Get system info. ************************** Please pick a service[1-3]: 3 Linux Linux 4.4.0-31-generic #50~14.04.1-Ubuntu SMP Wed Jul 13 01:07:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux chunli@Linux:~/boost$ nc 127.0.0.1 8868 Services ************************** [1] Get current time. [2] Who‘s online. [3] Get system info. ************************** Please pick a service[1-3]: 4 Sorry, no such service. chunli@Linux:~/boost$
多线程的tcp 同步服务器
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <fstream> #include <sstream> #include <boost/asio.hpp> #include <boost/shared_ptr.hpp> #include <boost/bind.hpp> #include <boost/thread.hpp> using namespace std; using boost::asio::ip::tcp; const char serviceList[] = "\n\t Services\n" "\t**************************\n" "\t[1] Get current time.\n" "\t[2] Who‘s online.\n" "\t[3] Get system info.\n" "\t**************************\n\n" "Please pick a service[1-3]: "; void getResult(const string& cmdPrefix, const char* outputFile, string& res) { // cmd == "w > who" string cmd(cmdPrefix + outputFile); system(cmd.c_str()); ifstream fin; fin.open(outputFile); if (fin) { ostringstream os; os << fin.rdbuf(); res = os.str(); } if (fin.is_open()) { fin.close(); } } string getServiceContent(const int& select) { string res; switch (select) { case 1: { time_t t = time(0); res = ctime(&t); break; } case 2: getResult("w > ", "who", res); break; case 3: getResult("uname -a > ", "uname", res); break; default: res = "Sorry, no such service.\n"; break; } return res; } typedef boost::shared_ptr<tcp::socket> SocketPtr; void handleIo(SocketPtr socket) { // 1, send service list to client boost::system::error_code ignored_error; boost::asio::write(*socket, boost::asio::buffer(serviceList), boost::asio::transfer_all(), ignored_error); // 2, receive selection from client char selection[20]; size_t n = socket->read_some(boost::asio::buffer(selection), ignored_error); // 3, send response string response = getServiceContent(atoi(selection)); boost::asio::write(*socket, boost::asio::buffer(response), boost::asio::transfer_all(), ignored_error); socket->close();//主动关闭socket } int main() { try { boost::asio::io_service io_service; // #1 tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 8868)); // #2 boost::thread_group grp; for (;;) { SocketPtr socket(new tcp::socket(io_service)); // #3 acceptor.accept(*socket); // #4 grp.create_thread(boost::bind(handleIo, socket)); } // #6 } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return 0; } chunli@Linux:~/boost$ g++ main.cpp -l boost_system -l boost_thread && ./a.out 多个客户端验证:不存在阻塞问题 chunli@Linux:~/boost$ nc 127.0.0.1 8868 Services ************************** [1] Get current time. [2] Who‘s online. [3] Get system info. ************************** Please pick a service[1-3]: -------------------------------- chunli@Linux:~$ chunli@Linux:~$ nc 127.0.0.1 8868 Services ************************** [1] Get current time. [2] Who‘s online. [3] Get system info. ************************** Please pick a service[1-3]:
tcp 同步客户端
chunli@Linux:~/boost$ cat client.cpp #include <iostream> #include <boost/asio.hpp> using namespace std; using boost::asio::ip::tcp; int main(int argc, char* argv[]) { try { // 1, 创建io_service对象 boost::asio::io_service io_service; // 2, 创建resolver对象关联到io_service对象 tcp::resolver resolver(io_service); // 3, 创建一个查询对象 tcp::resolver::query query("localhost", "8868"); // 4, 用resolver对象和查询对象获取可用服务器地址 tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); tcp::resolver::iterator end; // 5, 创建tcp::socket对象,关联到io_service tcp::socket socket(io_service); // 6, socket对象发起到服务器端的同步连接操作 boost::system::error_code error = boost::asio::error::host_not_found; while (error && endpoint_iterator != end) { socket.close(); socket.connect(*endpoint_iterator++, error); } if (error) // 如果没有一个地址能连接成功,则抛出异常 throw boost::system::system_error(error); // 7, 一系列 同步read()和write() char buf[512]; // receive service list from server // size_t len = socket.read_some(boost::asio::buffer(buf), error); // size_t len = socket.receive(boost::asio::buffer(buf), 0, error); size_t len = boost::asio::read(socket, boost::asio::buffer(buf), boost::asio::transfer_at_least(1), error); buf[len] = ‘\0‘; cout << buf; string selection; cin >> selection; // send selection to server // boost::asio::write(socket, boost::asio::buffer(selection), // boost::asio::transfer_all(), error); // socket.write_some(boost::asio::buffer(selection,selection.size()), error); socket.send(boost::asio::buffer(selection,selection.size()),0, error); // receive response from server len = socket.read_some(boost::asio::buffer(buf), error); buf[len] = ‘\0‘; cout << buf; } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return 0; } chunli@Linux:~/boost$ g++ client.cpp -l boost_system -lpthread -o client && ./client Services ************************** [1] Get current time. [2] Who‘s online. [3] Get system info. ************************** Please pick a service[1-3]:
boost 域名地址解析
chunli@Linux:~/boost$ cat client.cpp #include <iostream> #include <boost/asio.hpp> using namespace std; using boost::asio::ip::tcp; int main(int argc, char* argv[]) { // 1, 创建io_service对象 boost::asio::io_service io_service; // 2, 创建resolver对象关联到io_service对象 tcp::resolver resolver(io_service); for (;;) { try { string host, port; cin >> host >> port; // 3, 创建一个查询对象 tcp::resolver::query query(host, port); // 4, 用resolver对象和查询对象获取可用服务器地址 tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); tcp::resolver::iterator end; // 5, 创建tcp::socket对象,关联到io_service tcp::socket socket(io_service); // 6, socket对象发起到服务器端的同步连接操作 boost::system::error_code error = boost::asio::error::host_not_found; while (endpoint_iterator != end) { cout << endpoint_iterator->endpoint() << endl; socket.close(); socket.connect(*endpoint_iterator++, error); } if (error) // 如果没有一个地址能连接成功,则抛出异常 throw boost::system::system_error(error); } catch (std::exception& e) { std::cerr << e.what() << std::endl; } } return 0; } chunli@Linux:~/boost$ chunli@Linux:~/boost$ g++ client.cpp -l boost_system -lpthread -o client && ./client www.baidu.com 443 115.239.210.27:443 115.239.211.112:443 www.taobao.com 80 101.227.208.227:80 101.227.208.226:80 114.80.174.46:80 222.73.134.63:80 114.80.174.47:80 51cto.com 80 123.56.215.220:80
tcp异步服务器
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> using namespace std; using boost::asio::ip::tcp; class Connection: public boost::enable_shared_from_this<Connection> { public: Connection(boost::asio::io_service& service) : sock(service) { } void start() { // sock.async_read_some(boost::asio::buffer(buf), boost::bind( // &Connection::handleRead, // #1 // shared_from_this(), boost::asio::placeholders::error)); boost::asio::async_read(sock, boost::asio::buffer(buf), boost::asio::transfer_at_least(1), boost::bind( &Connection::handleRead, // #1 shared_from_this(), boost::asio::placeholders::error)); } tcp::socket& getSocket() { return sock; } private: void handleRead(const boost::system::error_code& error) { if (!error) { cout << "recv from: " << sock.remote_endpoint().address() << ":" << sock.remote_endpoint().port() << endl; // boost::asio::async_write(sock, boost::asio::buffer(buf), // boost::bind( // &Connection::handleWrite, // #2 // shared_from_this(), // boost::asio::placeholders::error)); sock.async_write_some(boost::asio::buffer(buf), boost::bind( &Connection::handleWrite, // #2 shared_from_this(), boost::asio::placeholders::error)); } } void handleWrite(const boost::system::error_code& error) { if (!error) { memset(buf, 0, 512); // 注意:重置buf sock.async_read_some(boost::asio::buffer(buf), boost::bind( &Connection::handleRead, // #3 shared_from_this(), boost::asio::placeholders::error)); } } private: tcp::socket sock; char buf[512]; }; typedef boost::shared_ptr<Connection> ConnectionPtr; class Server { public: Server(boost::asio::io_service& service) : acceptor(service, tcp::endpoint(tcp::v4(), 8080)) { start(); } private: void start() { ConnectionPtr conn(new Connection(acceptor.get_io_service())); acceptor.async_accept(conn->getSocket(), boost::bind( &Server::handleAccept, this, conn, boost::asio::placeholders::error)); } void handleAccept(ConnectionPtr con, const boost::system::error_code& error) { if (!error) { con->start(); start(); } } private: tcp::acceptor acceptor; }; int main() { try { boost::asio::io_service service; Server server(service); service.run(); // 注意:与同步I/O不同,异步I/O需要调用run() } catch (exception& e) { cout << e.what() << endl; } return 0; } chunli@Linux:~/boost$ g++ main.cpp -l boost_system -l boost_thread && ./a.out chunli@Linux:~/boost$ nc 127.0.0.1 8080 hello hello hello World hello World
tcp 异步客户端
chunli@Linux:~/boost$ cat client.cpp #include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> using namespace std; using namespace boost::asio::ip; class Client { public: Client(boost::asio::io_service& service,tcp::resolver::iterator endpointIterator):sock(service) { tcp::endpoint endpoint = *endpointIterator; sock.async_connect(endpoint, boost::bind(&Client::handleConnect, this,boost::asio::placeholders::error, ++endpointIterator)); } private: void handleConnect(const boost::system::error_code& error,tcp::resolver::iterator endpointIterator) { if (!error) { memset(buf, 0, 512); cin.getline(buf, BUF_SIZE); boost::asio::async_write(sock,boost::asio::buffer(buf, strlen(buf)), boost::bind(&Client::handleWrite,this,boost::asio::placeholders::error)); } else if (endpointIterator != tcp::resolver::iterator()) { sock.close(); tcp::endpoint endpoint = *endpointIterator; sock.async_connect(endpoint, boost::bind(&Client::handleConnect,this, boost::asio::placeholders::error, ++endpointIterator)); } } void handleRead(const boost::system::error_code& error) { if (!error) { cout << buf << endl; // print received message memset(buf, 0, 512); cin.getline(buf, BUF_SIZE); boost::asio::async_write(sock,boost::asio::buffer(buf, strlen(buf)), boost::bind(&Client::handleWrite,this,boost::asio::placeholders::error)); } } void handleWrite(const boost::system::error_code& error) { if (!error) { memset(buf, 0, 512); // 注意:重置buf sock.async_read_some(boost::asio::buffer(buf),boost::bind(&Client::handleRead, this,boost::asio::placeholders::error)); } } private: tcp::socket sock; enum { BUF_SIZE = 512 }; char buf[BUF_SIZE]; }; int main() { try { boost::asio::io_service service; tcp::resolver resolver(service); tcp::resolver::query query("localhost", "8868"); tcp::resolver::iterator iterator = resolver.resolve(query); tcp::endpoint addr(address::from_string("127.0.0.1"), 8868); Client client(service, iterator); service.run(); } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << "\n"; } return 0; } chunli@Linux:~/boost$ g++ client.cpp -l boost_system -lpthread -o client && ./client hello hello haha haha
UDP同步服务器
chunli@Linux:~/boost$ cat server.cpp #include <iostream> #include <boost/asio.hpp> using namespace std; using boost::asio::ip::udp; int main() { try { boost::asio::io_service service; // #1 udp::socket socket(service, udp::endpoint(udp::v4(), 8868)); //#2 char buf[512]; for (;;) { memset(buf, 0, 512); udp::endpoint remoteEndpoint; // #3 boost::system::error_code error; size_t len = socket.receive_from(boost::asio::buffer(buf), remoteEndpoint, 0, error);//#4 if (error && error != boost::asio::error::message_size) throw boost::system::system_error(error); boost::system::error_code ignoredError; socket.send_to(boost::asio::buffer(buf, len), remoteEndpoint, 0, ignoredError); // #5 } } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return 0; } chunli@Linux:~/boost$ g++ server.cpp -lboost_system -o S && ./S chunli@Linux:~$ netstat -unlp Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name udp 0 0 0.0.0.0:631 0.0.0.0:* - udp 0 0 0.0.0.0:8868 0.0.0.0:* 2050/S chunli@Linux:~$ nc -u 127.0.0.1 8868 hello hello 中国上海! 中国上海!
UDP同步客户端
chunli@Linux:~/boost$ cat client.cpp #include <iostream> #include <boost/asio.hpp> using namespace std; using boost::asio::ip::udp; int main(int argc, char* argv[]) { try { boost::asio::io_service service; // #1 udp::resolver resolver(service); // #2 udp::resolver::query query(udp::v4(), "localhost", "8868"); // #3 udp::endpoint receiverEndpoint = *resolver.resolve(query); // #4 // udp::socket socket(service); // socket.open(udp::v4()); // #5 // udp::endpoint receiverEndpoint(boost::asio::ip::address::from_string("192.168.0.101"), 51179); udp::socket socket(service, udp::v4());// #5 char buf[512]; for (;;) { memset(buf, 0, 512); cin.getline(buf, 512); socket.send_to(boost::asio::buffer(buf, strlen(buf)), receiverEndpoint); // #6 memset(buf, 0, 512); udp::endpoint senderEndpoint; // #7 socket.receive_from(boost::asio::buffer(buf), senderEndpoint); // #8 cout << buf << endl; } } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return 0; } chunli@Linux:~/boost$ g++ client.cpp -lboost_system -pthread -o C && ./C 中国上海! 中国上海! Hello Boost asio! Hello Boost asio!
UDP异步服务器
chunli@Linux:~/boost$ cat server.cpp #include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> using namespace std; using boost::asio::ip::udp; class Server { public: Server(boost::asio::io_service& service) : sock(service, udp::endpoint(udp::v4(), 8868)) { start(); } private: void start() { memset(buf, 0, BUF_SIZE); sock.async_receive_from(boost::asio::buffer(buf), remoteEndpoint, boost::bind(&Server::handleReceive, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void handleReceive(const boost::system::error_code& error, std::size_t bytes_transferred) { if (!error || error == boost::asio::error::message_size) { cout << remoteEndpoint << endl; sock.async_send_to(boost::asio::buffer(buf, bytes_transferred), remoteEndpoint, boost::bind(&Server::handleSend, this, boost::asio::placeholders::error)); start(); } } void handleSend(const boost::system::error_code& /*error*/) { } private: udp::socket sock; udp::endpoint remoteEndpoint; enum { BUF_SIZE = 512 }; char buf[BUF_SIZE]; }; int main() { try { boost::asio::io_service service; Server server(service); service.run(); // 注意:一定要调用 run()函数 } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return 0; } chunli@Linux:~/boost$ chunli@Linux:~/boost$ g++ server.cpp -lboost_system -o S && ./S 127.0.0.1:36398 127.0.0.1:36398
UDP异步客户端
chunli@Linux:~/boost$ cat client.cpp #include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> using namespace std; using boost::asio::ip::udp; class Client { public: Client(boost::asio::io_service& service, const udp::endpoint& remote) : remoteEndpoint(remote), sock(service, udp::v4()) { // sock.open(udp::v4()); start(); } private: void start() { memset(buf, 0, BUF_SIZE); cin.getline(buf, BUF_SIZE); sock.async_send_to(boost::asio::buffer(buf, strlen(buf)), remoteEndpoint, boost::bind(&Client::handleSend, this, boost::asio::placeholders::error)); } void handleSend(const boost::system::error_code& error) { if (!error) { memset(buf, 0, BUF_SIZE); udp::endpoint local; sock.async_receive_from(boost::asio::buffer(buf, BUF_SIZE), local, boost::bind(&Client::handleReceive, this, boost::asio::placeholders::error)); } } void handleReceive(const boost::system::error_code& error) { if (!error) { cout << buf << endl; start(); } } private: udp::endpoint remoteEndpoint; udp::socket sock; enum { BUF_SIZE = 512 }; char buf[BUF_SIZE]; }; int main() { try { boost::asio::io_service service; udp::resolver resolver(service); udp::resolver::query query(udp::v4(), "localhost", "8868"); udp::endpoint receiverEndpoint = *resolver.resolve(query); cout << receiverEndpoint << endl; // cout << receiverEndpoint.address().to_string() << endl; // cout << receiverEndpoint.port() << endl; Client c(service, receiverEndpoint); service.run(); } catch (exception& e) { cout << e.what() << endl; } } chunli@Linux:~/boost$ g++ client.cpp -lboost_system -pthread -o C && ./C 127.0.0.1:8868 haha haha 中国上海 中国上海
HTTP同步客户端
chunli@Linux:~/boost$ cat client.cpp #include <iostream> #include <istream> #include <ostream> #include <string> #include <boost/asio.hpp> using boost::asio::ip::tcp; int main(int argc, char* argv[]) { try { if (argc != 3) { std::cout << "Usage: sync_client <server> <path>\n"; std::cout << "Example:\n"; std::cout << " sync_client www.boost.org /LICENSE_1_0.txt\n"; return 1; } boost::asio::io_service io_service; // Get a list of endpoints corresponding to the server name. tcp::resolver resolver(io_service); tcp::resolver::query query(argv[1], "80"); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); tcp::resolver::iterator end; // Try each endpoint until we successfully establish a connection. tcp::socket socket(io_service); boost::system::error_code error = boost::asio::error::host_not_found; while (error && endpoint_iterator != end) { socket.close(); socket.connect(*endpoint_iterator++, error); } if (error) throw boost::system::system_error(error); // Form the request. We specify the "Connection: close" header so that the // server will close the socket after transmitting the response. This will // allow us to treat all data up until the EOF as the content. boost::asio::streambuf request; std::ostream request_stream(&request); request_stream << "GET " << argv[2] << " HTTP/1.0\r\n"; request_stream << "Host: " << argv[1] << "\r\n"; request_stream << "Accept: */*\r\n"; request_stream << "Connection: close\r\n\r\n"; // Send the request. boost::asio::write(socket, request); // Read the response status line. boost::asio::streambuf response; boost::asio::read_until(socket, response, "\r\n"); // Check that response is OK. std::istream response_stream(&response); std::string http_version; response_stream >> http_version; unsigned int status_code; response_stream >> status_code; std::string status_message; std::getline(response_stream, status_message); if (!response_stream || http_version.substr(0, 5) != "HTTP/") { std::cout << "Invalid response\n"; return 1; } if (status_code != 200) { std::cout << "Response returned with status code " << status_code << "\n"; return 1; } // Read the response headers, which are terminated by a blank line. boost::asio::read_until(socket, response, "\r\n\r\n"); // Process the response headers. std::string header; while (std::getline(response_stream, header) && header != "\r"); std::cout << header << "\n"; std::cout << "\n"; // Write whatever content we already have to output. if (response.size() > 0) std::cout << &response; // Read until EOF, writing data to output as we go. while (boost::asio::read(socket, response, boost::asio::transfer_at_least(1), error)) std::cout << &response; if (error != boost::asio::error::eof) throw boost::system::system_error(error); } catch (std::exception& e) { std::cout << "Exception: " << e.what() << "\n"; } return 0; } chunli@Linux:~/boost$ g++ client.cpp -lboost_system -pthread -o C && ./C www.boost.org /LICENSE_1_0.txt Boost Software License - Version 1.0 - August 17th, 2003 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. chunli@Linux:~/boost$
HTTP异步客户端
chunli@Linux:~/boost$ cat client.cpp #include <iostream> #include <istream> #include <ostream> #include <string> #include <boost/asio.hpp> #include <boost/bind.hpp> using boost::asio::ip::tcp; class client { public: client(boost::asio::io_service& io_service, const std::string& server, const std::string& path) : resolver_(io_service), socket_(io_service) { // Form the request. We specify the "Connection: close" header so that the // server will close the socket after transmitting the response. This will // allow us to treat all data up until the EOF as the content. std::ostream request_stream(&request_); request_stream << "GET " << path << " HTTP/1.0\r\n"; request_stream << "Host: " << server << "\r\n"; request_stream << "Accept: */*\r\n"; request_stream << "Connection: close\r\n\r\n"; // Start an asynchronous resolve to translate the server and service names // into a list of endpoints. tcp::resolver::query query(server, "http"); resolver_.async_resolve(query, boost::bind(&client::handle_resolve, this, boost::asio::placeholders::error, boost::asio::placeholders::iterator)); } private: void handle_resolve(const boost::system::error_code& err, tcp::resolver::iterator endpoint_iterator) { if (!err) { // Attempt a connection to the first endpoint in the list. Each endpoint // will be tried until we successfully establish a connection. tcp::endpoint endpoint = *endpoint_iterator; socket_.async_connect(endpoint, boost::bind( &client::handle_connect, this, boost::asio::placeholders::error, ++endpoint_iterator)); } else { std::cout << "Error: " << err.message() << "\n"; } } void handle_connect(const boost::system::error_code& err, tcp::resolver::iterator endpoint_iterator) { if (!err) { // The connection was successful. Send the request. boost::asio::async_write(socket_, request_, boost::bind( &client::handle_write_request, this, boost::asio::placeholders::error)); } else if (endpoint_iterator != tcp::resolver::iterator()) { // The connection failed. Try the next endpoint in the list. socket_.close(); tcp::endpoint endpoint = *endpoint_iterator; socket_.async_connect(endpoint, boost::bind( &client::handle_connect, this, boost::asio::placeholders::error, ++endpoint_iterator)); } else { std::cout << "Error: " << err.message() << "\n"; } } void handle_write_request(const boost::system::error_code& err) { if (!err) { // Read the response status line. boost::asio::async_read_until(socket_, response_, "\r\n", boost::bind(&client::handle_read_status_line, this, boost::asio::placeholders::error)); } else { std::cout << "Error: " << err.message() << "\n"; } } void handle_read_status_line(const boost::system::error_code& err) { if (!err) { // Check that response is OK. std::istream response_stream(&response_); std::string http_version; response_stream >> http_version; unsigned int status_code; response_stream >> status_code; std::string status_message; std::getline(response_stream, status_message); if (!response_stream || http_version.substr(0, 5) != "HTTP/") { std::cout << "Invalid response\n"; return; } if (status_code != 200) { std::cout << "Response returned with status code "; std::cout << status_code << "\n"; return; } // Read the response headers, which are terminated by a blank line. boost::asio::async_read_until(socket_, response_, "\r\n\r\n", boost::bind(&client::handle_read_headers, this, boost::asio::placeholders::error)); } else { std::cout << "Error: " << err << "\n"; } } void handle_read_headers(const boost::system::error_code& err) { if (!err) { // Process the response headers. std::istream response_stream(&response_); std::string header; while (std::getline(response_stream, header) && header != "\r") std::cout << header << "\n"; std::cout << "\n"; // Write whatever content we already have to output. if (response_.size() > 0) std::cout << &response_; // Start reading remaining data until EOF. boost::asio::async_read(socket_, response_, boost::asio::transfer_at_least(1), boost::bind( &client::handle_read_content, this, boost::asio::placeholders::error)); } else { std::cout << "Error: " << err << "\n"; } } void handle_read_content(const boost::system::error_code& err) { if (!err) { // Write all of the data that has been read so far. std::cout << &response_; // Continue reading remaining data until EOF. boost::asio::async_read(socket_, response_, boost::asio::transfer_at_least(1), boost::bind( &client::handle_read_content, this, boost::asio::placeholders::error)); } else if (err != boost::asio::error::eof) { std::cout << "Error: " << err << "\n"; } } tcp::resolver resolver_; tcp::socket socket_; boost::asio::streambuf request_; boost::asio::streambuf response_; }; int main(int argc, char* argv[]) { try { if (argc != 3) { std::cout << "Usage: async_client <server> <path>\n"; std::cout << "Example:\n"; std::cout << " async_client www.boost.org /LICENSE_1_0.txt\n"; return 1; } boost::asio::io_service io_service; client c(io_service, argv[1], argv[2]); io_service.run(); } catch (std::exception& e) { std::cout << "Exception: " << e.what() << "\n"; } return 0; } chunli@Linux:~/boost$ g++ client.cpp -lboost_system -pthread -o C && ./C www.boost.org /LICENSE_1_0.txt Date: Wed, 28 Dec 2016 05:06:25 GMT Server: Apache/2.2.15 (Red Hat) Last-Modified: Sun, 15 Dec 2013 02:55:11 GMT ETag: "2c53e9-53a-4ed89d2e171f1" Accept-Ranges: bytes Content-Length: 1338 Connection: close Content-Type: text/plain Boost Software License - Version 1.0 - August 17th, 2003 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. chunli@Linux:~/boost$
同步实验:
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <boost/asio.hpp> #include <boost/date_time/posix_time/posix_time.hpp> int main() { boost::asio::io_service io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(5)); t.wait(); std::cout << "Hello, world!\n"; return 0; } chunli@Linux:~/boost$ g++ main.cpp -lboost_system && ./a.out Hello, world! chunli@Linux:~/boost$
异步实验
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <boost/asio.hpp> #include <boost/date_time/posix_time/posix_time.hpp> void print(const boost::system::error_code& /*e*/) { std::cout << "Hello, world!\n"; } int main() { boost::asio::io_service io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(5)); t.async_wait(print); std::cout << "---------------------" << std::endl; io.run(); return 0; } chunli@Linux:~/boost$ g++ main.cpp -lboost_system && ./a.out --------------------- Hello, world! chunli@Linux:~/boost$
多线程异步实验
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <boost/asio.hpp> #include <boost/thread.hpp> #include <boost/bind.hpp> #include <boost/date_time/posix_time/posix_time.hpp> class printer { public: printer(boost::asio::io_service& io) : strand_(io), timer1_(io, boost::posix_time::seconds(1)), timer2_(io, boost::posix_time::seconds(1)), count_(0) { timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this))); timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this))); } ~printer() { std::cout << "Final count is " << count_ << "\n"; } void print1() { if (count_ < 10) { std::cout << "Timer 1: " << count_ << "\n"; ++count_; timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1)); timer1_.async_wait( strand_.wrap(boost::bind(&printer::print1, this))); } } void print2() { if (count_ < 10) { std::cout << "Timer 2: " << count_ << "\n"; ++count_; timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1)); timer2_.async_wait( strand_.wrap(boost::bind(&printer::print2, this))); } } private: boost::asio::strand strand_; boost::asio::deadline_timer timer1_; boost::asio::deadline_timer timer2_; int count_; }; int main() { boost::asio::io_service io; printer p(io); boost::thread t(boost::bind(&boost::asio::io_service::run, &io)); io.run(); t.join(); return 0; } chunli@Linux:~/boost$ g++ main.cpp -lboost_system -lboost_thread && ./a.out Timer 1: 0 Timer 2: 1 Timer 1: 2 Timer 2: 3 Timer 1: 4 Timer 2: 5 Timer 1: 6 Timer 2: 7 Timer 1: 8 Timer 2: 9 Final count is 10 chunli@Linux:~/boost$
本文出自 “魂斗罗” 博客,请务必保留此出处http://990487026.blog.51cto.com/10133282/1886852
10 C++ Boost ASIO网路通信库 TCP/UDP,HTTP
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。