我一直在线上学习Asio的异步网络,所以如果我犯了一个非常明显的错误,那就是你的解释。异步读取完成,但缓冲区不包含预期的结果
尽管如此,我写了一个程序,它同时设置客户端和服务器,并尝试在两者之间进行通信。简单地连接并发送请求以发送/接收数据似乎工作正常,但数据本身并未发送。
#define ASIO_STANDALONE
#include<asio.hpp>
#include<thread>
#include<iostream>
#include<vector>
#include<array>
#include<mutex>
#include<memory>
#include<functional>
#define IPADDRESS "127.0.0.1"
#define PORT "6118"
enum side_type {
t_server, t_client
};
std::mutex m_lock;
std::array<char, 32> clientBuffer;
std::array<char, 32> serverBuffer;
bool stop(false);
void read_function(const asio::error_code&, size_t, std::shared_ptr<asio::ip::tcp::socket>, std::array<char, 32> &, side_type &);
void write_function(const asio::error_code&, size_t, std::shared_ptr<asio::ip::tcp::socket>, std::array<char, 32> &, side_type &);
void read_function(const asio::error_code& ec, size_t bytes_read, std::shared_ptr<asio::ip::tcp::socket> socket, std::array<char, 32> & buffer, side_type & type) {
if (ec) return;
using namespace std;
using namespace std::placeholders;
char value = buffer[0];
{
lock_guard<mutex> guard(m_lock);
string type_str = type == t_server ? "Server" : "Client";
cout << "Value of " << int(value) << " read by " << type_str << "." << endl;
}
if (value >= 100) stop = true;
else {
if(type == t_server)
buffer[0] = value + 1;
socket->async_write_some(asio::buffer(&buffer[0], buffer.max_size()), bind(write_function, _1, _2, socket, buffer, type));
}
}
void write_function(const asio::error_code& ec, size_t bytes_written, std::shared_ptr<asio::ip::tcp::socket> socket, std::array<char, 32> & buffer, side_type & type) {
if (ec) return;
using namespace std;
using namespace std::placeholders;
socket->async_read_some(asio::buffer(&buffer[0], buffer.max_size()), bind(read_function, _1, _2, socket, buffer, type));
}
void work_function(std::shared_ptr<asio::io_service> io_service) {
using namespace std;
asio::error_code ec;
while (!ec) {
try {
io_service->run(ec);
break;
}
catch (exception & e) {
lock_guard<mutex> guard(m_lock);
cout << "Exception thrown: \"" << e.what() << "\"." << endl;
}
}
}
void connect_function(const asio::error_code & ec, std::shared_ptr<asio::ip::tcp::socket> socket) {
using namespace std;
using namespace std::placeholders;
lock_guard<mutex> guard(m_lock);
if (ec) {
cout << "Error Connecting: " << ec << endl;
}
else {
cout << "Successful Connection!" << endl;
socket->async_read_some(asio::buffer(&clientBuffer[0], clientBuffer.max_size()), bind(read_function, _1, _2, socket, clientBuffer, t_client));
}
}
void accept_function(const asio::error_code & ec, std::shared_ptr<asio::ip::tcp::socket> socket) {
using namespace std;
using namespace std::placeholders;
lock_guard<mutex> guard(m_lock);
if (ec) {
cout << "Error Accepting: " << ec << endl;
}
else {
cout << "Successful Acception!" << endl;
serverBuffer[0] = 0;
socket->async_write_some(asio::buffer(&serverBuffer[0], serverBuffer.max_size()), bind(write_function, _1, _2, socket, serverBuffer, t_server));
}
}
int main(int argc, char** argv) {
using namespace std;
using namespace std::placeholders;
shared_ptr<asio::io_service> io_service(new asio::io_service());
shared_ptr<asio::io_service::work> work(new asio::io_service::work(*io_service));
vector<shared_ptr<thread>> threads;
int num_of_threads = thread::hardware_concurrency();
for (auto i = 0; i < thread::hardware_concurrency(); i++) {
threads.push_back(shared_ptr<thread>(new thread(work_function, io_service)));
}
using namespace asio::ip;
tcp::resolver resolver(*io_service);
tcp::resolver::query query(IPADDRESS, PORT);
tcp::resolver::iterator iterator = resolver.resolve(query);
tcp::endpoint endpoint = *iterator;
cout << "Connecting to " << endpoint << endl;
shared_ptr<tcp::acceptor> acceptor(new tcp::acceptor(*io_service));
shared_ptr<tcp::socket> acc_socket(new tcp::socket(*io_service));
shared_ptr<tcp::socket> socket(new tcp::socket(*io_service));
acceptor->open(endpoint.protocol());
acceptor->set_option(tcp::acceptor::reuse_address(false));
acceptor->bind(endpoint);
acceptor->listen(asio::socket_base::max_connections);
acceptor->async_accept(*acc_socket, bind(accept_function, _1, acc_socket));
asio::error_code ec;
socket->async_connect(endpoint, bind(connect_function, _1, socket));
//while (!stop);
cout << "Press Any Key to Continue..." << endl;
cin.get();
socket->shutdown(tcp::socket::shutdown_both, ec);
socket->close(ec);
work.reset();
while (!io_service->stopped());
for (shared_ptr<thread> & t : threads) {
t->join();
}
return 0;
}
作为输出,我已经得到了以下内容:
Connecting to 127.0.0.1:6118
Press Any Key to Continue...
Successful Connection!
Successful Acception!
Value of 0 read by Client.
Value of 0 read by Server.
Value of 0 read by Client.
Value of 1 read by Server.
Value of 0 read by Client.
Value of 2 read by Server.
Value of 0 read by Client.
Value of 3 read by Server.
......
Value of 0 read by Client.
Value of 98 read by Server.
Value of 0 read by Client.
Value of 99 read by Server.
Value of 0 read by Client.
Value of 100 read by Server.
不过,我很期待是:
Connecting to 127.0.0.1:6118
Press Any Key to Continue...
Successful Connection!
Successful Acception!
Value of 0 read by Client.
Value of 0 read by Server.
Value of 1 read by Client.
Value of 1 read by Server.
Value of 2 read by Client.
Value of 2 read by Server.
Value of 3 read by Client.
Value of 3 read by Server.
......
Value of 98 read by Client.
Value of 98 read by Server.
Value of 99 read by Client.
Value of 99 read by Server.
Value of 100 read by Client.
Value of 100 read by Server.
显然发生了什么是服务器缓冲区得到更新(当我手动增加值时),而Client缓冲区永远不会被async_read_some函数更新。此外,由于客户端缓冲区永远不会更新,因此服务器只读旧值(也未更新),因此在技术上也具有不正确的输出。但是,我不知道什么是错的。我按照我认为应该的方式传递所有缓冲区,并且所有函数似乎都被正确绑定,但数据未被传递。那么我做错了什么?
什么版本提升您使用的是? – JVene
或者,如果不使用boost,什么版本的asio? – JVene
我正在使用Asio的非Boost版本。版本1.10.6。下面是最新的非开发版代码:http://think-async.com/Asio/Download – Xirema