我创建了主cpp文件和三个类来创建异步服务器。 分别为server
,service
和acceptor
。 但是,它们导致了生成过程中的错误,即使visual studio 2019环境中没有错误。 我试图修复错误,但大多数错误都发生在其他文件中,所以我自己都想不起来。
主
#include "Server.h"
#include <iostream>
#include <boost/asio.hpp>
#include <thread>
#include <atomic>
#include <memory>
#define DEFAULT_THREAD_SIZE 2;
using namespace boost;
int main()
{
unsigned short port_num;
std::cin >> port_num;
try {
Server srv;
unsigned int threads = std::thread::hardware_concurrency() * 2;
if (threads == 0) {
threads = DEFAULT_THREAD_SIZE;
}
std::cout << "\nPort - " << port_num << "\nServer start\n";
srv.Start(port_num, threads);
while (1) {
std::cin >> srv;
}
}
catch (system::system_error& e) {
std::cout << "\nError code: " << e.code() << "\nError Message\n" << e.what();
}
return 0;
}
这包括Server.h,它定义了服务器类。
#include "Acceptor.h"
#include <boost/asio.hpp>
#include <thread>
#include <atomic>
#include <memory>
using namespace boost;
class Server
{
public:
Server();
void Start(unsigned short port_num, unsigned int threads);
void Stop();
int Command(std::string& str);
private:
asio::io_service mios;
std::unique_ptr<asio::io_service::work> mWork;
std::unique_ptr<Acceptor> mAcceptor;
std::vector <std::unique_ptr<std::thread>> mThreads;
};
std::istream& operator>>(std::istream& is, Server& srv);
下面是实现,server.cpp。
#include "Server.h"
Server::Server() {
mWork.reset(new asio::io_service::work(mios));
}
void Server::Start(unsigned short port_num, unsigned int threads) {
assert(thread > 0);
mAcceptor.reset(new Acceptor(mios, port_num));
mAcceptor->Start();
for (int i = 0; i < threads; i++) {
std::unique_ptr<std::thread> th(new std::thread([this]() {mios.run(); }));
mThreads.push_back(std::move(th));
}
}
void Server::Stop() {
mAcceptor->Stop();
mios.stop();
for (auto& th : mThreads) {
th->join();
}
}
int Server::Command(std::string& str) {
return 0;
}
std::istream& operator>>(std::istream& is, Server& srv) {
std::string str;
is >> str;
srv.Command(str);
return is;
}
这是Acceptor类。
#include "Service.h"
#include <boost/asio.hpp>
#include <thread>
#include <atomic>
#include <memory>
using namespace boost;
class Acceptor
{
public:
Acceptor(asio::io_service& ios, unsigned short port_num);
void Start();
void Stop();
private:
std::shared_ptr<asio::io_service> mios;
std::shared_ptr<asio::ip::tcp::acceptor> mAcceptor;
std::atomic<bool> mIsStopped;
void InitAccept();
void OnAccept(const system::error_code ec, std::shared_ptr<asio::ip::tcp::socket> sock);
};
#include "Acceptor.h"
Acceptor::Acceptor(asio::io_service& ios, unsigned short port_num) {
mios = std::make_shared<asio::io_service>(ios);
mAcceptor = std::make_shared<asio::ip::tcp::acceptor>(mios, asio::ip::tcp::endpoint(asio::ip::address_v4::any(), port_num));
mIsStopped = false;
}
void Acceptor::Start() {
mAcceptor->listen();
InitAccept();
}
void Acceptor::Stop() {
mIsStopped.store(true);
}
void Acceptor::InitAccept() {
std::shared_ptr<asio::ip::tcp::socket> sock(new asio::ip::tcp::socket(mios));
mAcceptor->async_accept(*sock, [this, sock](const system::error_code& error) {OnAccept(error, sock);});
}
void Acceptor::OnAccept(const system::error_code ec, std::shared_ptr<asio::ip::tcp::socket> sock) {
if (ec.value() == 0 || ER) {
(new Service(sock))->StartHandling();
}
else{
std::cout << "Error code:" << ec.value() << "error " << "Error message: " << ec.message() << "\n";
}
if (!mIsStopped.load()) {
InitAccept();
}
else {
mAcceptor->close();
}
}
服务类
#define ER true
#include <iostream>
#include <boost/asio.hpp>
#include <thread>
#include <atomic>
#include <memory>
using namespace boost;
class Service
{
public:
Service(std::shared_ptr<asio::ip::tcp::socket> sock);
void StartHandling();
private:
void OnRequestReceived(const boost::system::error_code& ec, std::size_t bytes_transferred);
std::string mReponse;
std::shared_ptr<asio::ip::tcp::socket> mSock;
asio::streambuf mRequest;
void OnReponseSent(const system::error_code& ec, std::size_t bytes_transferred);
void OnFinish();
std::string ProcessRequest(asio::streambuf& request);
};
#include "Service.h"
Service::Service(std::shared_ptr<asio::ip::tcp::socket> sock){
mSock = sock;
}
void Service::StartHandling() {
asio::async_read_until(mSock, mRequest, '\n', [this](const system::error_code ec, std::size_t bytes_transferred) {OnRequestReceived(ec, bytes_transferred); });
}
void Service::OnRequestReceived(const system::error_code& ec, std::size_t bytes_transferred) {
if (ec.value() != 0 || ER) {
std::cout << "Error code:" << ec.value() << "Error message: " << ec.message() << "\n";
OnFinish();
return;
}
mReponse = ProcessRequest(mRequest);
asio::async_write(mSock, asio::buffer(mReponse), [this](const system::error_code& ec, std::size_t bytes_transferred) {OnReponseSent(ec, bytes_transferred); });
}
void Service::OnReponseSent(const system::error_code& ec, std::size_t bytes_transferred) {
if (ec.value() != 0 || ER) {
std::cout << "Error code:" << ec.value() << "Error message: " << ec.message() << "\n";
}
OnFinish();
}
void Service::OnFinish() {
delete this;
}
std::string Service::ProcessRequest(asio::streambuf& request) {
std::string reponse;
std::istream input(&request);
std::getline(input, reponse);
assert(reponse.back() == '\n');
return reponse;
}
我不知道该怎么办。 我想自己做,但我连调试都做不到,因为我搞不清楚问题出在哪里,而且它没有构建。
它根本无法编译。 我真的很想知道,人们怎么能在注意到这些东西不编译之前就想出/这么多/代码。
规则1:小步走(这对专业人士也同样适用,只是他们把它内化了而已)。
你在做一些事情,比如:
mios = std::make_shared<asio::io_service>(ios);
这要求IO_service
是可复制的(实际情况并非如此)。 您可能会将MIOS
作为引用:
asio::io_service& mios;
对shared_ptr的“迷信”使用似乎随处可见。
事实是…
assert(thread > 0);
拼写错误的threads
表示您可能正在生成仅限发行版的生成。
void Service::StartHandling() {
asio::async_read_until(mSock, mRequest, '\n', [this](const system::error_code ec, std::size_t bytes_transferred) {OnRequestReceived(ec, bytes_transferred); });
}
这会触发错误:
/home/sehe/custom/boost_1_73_0/boost/asio/impl/read_until.hpp|959 col 53| error: no type named ‘executor_type’ in ‘class std::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >’
显然您指的是*msock
。 以后相同:
asio::async_write(*mSock, asio::buffer(mReponse), [this](const system::error_code& ec, std::size_t bytes_transferred) {OnReponseSent(ec, bytes_transferred); });
指针不是它所指向的对象--即使是智能指针也不是。 智能指针的意义[原文如此]不是让C++等同于(比如说)Java--如果你想要的话,你应该使用Java。
通过这些,它编译了:Live On Wandbox