我一直在線上學習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