gpt4 book ai didi

c++ - 如何创建可以同时处理多个客户端的 Boost.Asio 服务器?

转载 作者:可可西里 更新时间:2023-11-01 02:58:03 24 4
gpt4 key购买 nike

我可以创建一个可以响应一个客户端的简单 TCP 服务器,但我不知道如何创建一个可以同时处理多个客户端的服务器。我已经提到了像 TCP 白天异步服务器这样的例子,但它只是将数据发送到客户端。我需要创建的是只要客户端存在就保持连接。 Client 和 Server 都将使用 Json 进行通信。考虑一种情况,客户端将提供 {"hello":"Client"},服务器应响应 {"Hello":"Server"},然后说另一个 {"message":"How are you?"} 及其响应 {"response": "Fine"}。我需要同时处理多个客户。我阅读了聊天服务器文档,但它太难理解了。有人可以提供有关如何使用 Boost.Asio 启动代码的基本流程吗?谢谢。

下面是给出的代码:

#include <ctime>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <json/reader.h>
#include <json/writer.h>

Json::Value GetRootFromJson(std::string json)
{
Json::Value root;
Json::Reader reader;
bool success = reader.parse(json, root);
return root;
}

std::string GetJsonFromRoot(Json::Value root)
{
Json::FastWriter writer;
std::string json = writer.write(root);
return json;

}

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);
}

class tcp_connection
: public boost::enable_shared_from_this<tcp_connection>
{
public:
typedef boost::shared_ptr<tcp_connection> pointer;

static pointer create(boost::asio::io_service& io_service)
{
return pointer(new tcp_connection(io_service));
}

tcp::socket& socket()
{
return socket_;
}

void start()
{
//message_ = make_daytime_string();

//Read from client, make json and send appropriate response
boost::asio::async_read(socket_, boost::asio::buffer(message_),
boost::bind(&tcp_connection::handle_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
std::string messageP(message_);
std::cout << messageP << std::endl;
Json::Value root = GetRootFromJson(messageP);
std::string isHello = root["hello"].asString();
std::string isMessage = root["message"].asString();
if(!isHello.empty())
{
std::string messageTemp = "{\"Hello\":\"Server\"}";
boost::asio::async_write(socket_, boost::asio::buffer(messageTemp),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}

if(!isMessage.empty())
{
std::string messageTemp = "{\"response\":\"Fine\"}";
boost::asio::async_write(socket_, boost::asio::buffer(messageTemp),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}



/*
boost::asio::async_write(socket_, boost::asio::buffer(message_),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
*/
}

private:
tcp_connection(boost::asio::io_service& io_service)
: socket_(io_service)
{
}

void handle_write(const boost::system::error_code& /*error*/,
size_t /*bytes_transferred*/)
{
}
void handle_read(const boost::system::error_code& /*error*/,
size_t /*bytes_transferred*/)
{
std::cout << "Handle Read of connection\n";
}

tcp::socket socket_;
std::string message_;
};

class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), 1936))
{
start_accept();
}

private:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.get_io_service());

acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::handle_accept, this, new_connection,
boost::asio::placeholders::error));
}

void handle_accept(tcp_connection::pointer new_connection,
const boost::system::error_code& error)
{
if (!error)
{
std::cout << "A client connected" << std::endl;
new_connection->start();
}

start_accept();
}

tcp::acceptor acceptor_;
};

int main()
{
try
{
boost::asio::io_service io_service;
tcp_server server(io_service);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}

运行这个给我:

Error 2 error C2679: binary '=' : no operator found which takes a right-hand operand of type 'const boost::asio::const_buffer' (or there is no acceptable conversion) C:\boost_1_55_0_dyn\boost\asio\detailconsuming_buffers.hpp 175

编辑:我添加了一个非常简单的客户端代码,它将发送 "{\"Hello\":\"Client\"}" 到服务器并且期望输出。但是sehe给的服务器代码无法进入handle_read

#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

int main(int argc, char* argv[])
{
try
{

boost::asio::io_service io_service;

tcp::resolver resolver(io_service);
tcp::resolver::query query("localhost", "1936");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);

tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);

std::string message = "{\"hello\":\"Client\"}";
std::cout << "Sending the message: " << message << std::endl;
socket.send(boost::asio::buffer(message));
std::cout << "Sent the message: " << message << std::endl;
boost::asio::streambuf buf;
size_t len;
std::string messageReceived;
boost::asio::streambuf::mutable_buffers_type mbuf = buf.prepare(512);
std::cout << "Now receiving message\n";
std::string messageServer;
try
{
boost::asio::streambuf buf;
size_t len;
boost::asio::streambuf::mutable_buffers_type mbuf = buf.prepare(512);
do {
len = socket.receive(mbuf);
std::cout << len << std::endl;
std::string str(boost::asio::buffers_begin(mbuf), boost::asio::buffers_begin(mbuf) + len);
messageServer = messageServer + str;
} while (len>=512);
}
catch (boost::system::system_error err)
{
std::cout << err.code() << " " << err.what();
}

std::cout << messageServer << std::endl;
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}

这是实现服务器的正确方法吗?谢谢。

最佳答案

如文件所示,

boost::asio::async_read(socket_, boost::asio::buffer(message_),

接受一个streambuf。

此外,它是一个异步操作,因此在发布读取操作之后和完成处理程序 (handle_read) 被回调。

以下至少为我编译:

#include <ctime>
#include <iostream>
#include <string>

#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>

#include <json/reader.h>
#include <json/writer.h>

namespace {
Json::Value to_json(std::string json)
{
Json::Value root;
Json::Reader reader;
/*bool success =*/ reader.parse(json, root);
return root;
}

std::string to_string(Json::Value root) // unused TODO FIXME
{
Json::FastWriter writer;
std::string json = writer.write(root);
return json;
}
}

using boost::asio::ip::tcp;

class tcp_connection : public boost::enable_shared_from_this<tcp_connection>
{
public:
typedef boost::shared_ptr<tcp_connection> pointer;

static pointer create(boost::asio::io_service& io_service)
{
return pointer(new tcp_connection(io_service));
}

tcp::socket& socket()
{
return socket_;
}

void start()
{
//Read from client, make json and send appropriate response
boost::asio::async_read(socket_, message_,
boost::bind(&tcp_connection::handle_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}

private:
tcp_connection(boost::asio::io_service& io_service)
: socket_(io_service)
{
}

void handle_write(const boost::system::error_code& /*error*/,
size_t /*bytes_transferred*/)
{
}

void handle_read(const boost::system::error_code& error, size_t bytes_transferred)
{
std::cout << "Handle Read of connection\n";

if (error && error != boost::asio::error::eof) {
std::cout << "Error: " << error.message() << "\n";
return;
}

std::string messageP;
{
std::stringstream ss;
ss << &message_;
ss.flush();
messageP = ss.str();
}

std::cout << messageP << std::endl;

Json::Value root = to_json(messageP);
std::string isHello = root["hello"].asString();
std::string isMessage = root["message"].asString();
if(!isHello.empty())
{
std::string messageTemp = "{\"Hello\":\"Server\"}";
boost::asio::async_write(socket_, boost::asio::buffer(messageTemp),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}

if(!isMessage.empty())
{
std::string messageTemp = "{\"response\":\"Fine\"}";
boost::asio::async_write(socket_, boost::asio::buffer(messageTemp),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
}

tcp::socket socket_;
boost::asio::streambuf message_;
};

class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), 1936))
{
start_accept();
}

private:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.get_io_service());

acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::handle_accept, this, new_connection,
boost::asio::placeholders::error));
}

void handle_accept(tcp_connection::pointer new_connection, const boost::system::error_code& error)
{
if (!error)
{
std::cout << "A client connected" << std::endl;
new_connection->start();
}

start_accept();
}

tcp::acceptor acceptor_;
};

int main()
{
try
{
boost::asio::io_service io_service;
tcp_server server(io_service);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}

关于c++ - 如何创建可以同时处理多个客户端的 Boost.Asio 服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31579362/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com