gpt4 book ai didi

c++ - boost::async_write 跳过部分字符串

转载 作者:行者123 更新时间:2023-11-28 05:05:12 25 4
gpt4 key购买 nike

我正在聊天。出于某种原因,在其他客户端之间分发用户消息时,由 Server::msgHandler 组合在一起的字符串被 Connection::write< 中的 async_write 屠杀,使其看起来只实际读取了该字符串的一部分。示例:

Constructed message: "Hello people by Jack"
Appears as: "by Jack"

那是 string str=Hello people 没有打印出来。起初我以为它与末尾的隐式 \0 有关,但这没有任何意义,而且,当我尝试 message 中字符串的不同位置时,我注意到如果 str 前面有其他文本,文本将显示为完全发出 str,或将其放在意想不到的地方。例如

writeMsg("It was said: \n"+str+" by \"name\"\n");
will appear as:
It was said
by "name"Hello People

完整的、最小的、可编译的示例:

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


#include <iostream>
#include <vector>
#include <deque>

typedef boost::asio::io_service io_service;
typedef boost::asio::ip::tcp tcp;

class Server;

class Connection : public boost::enable_shared_from_this<Connection> {
io_service::strand strand;
tcp::socket soc;
std::deque<std::string> msgBuff;
boost::asio::streambuf buf;
Server* server;
void(Server::*serverHandler)(std::string);

private:
Connection(io_service& service) :soc(service), strand(service){

}

void writeStranded(std::string msg){
msgBuff.push_back(msg);
if (msgBuff.size() > 1)return;
write();

}
void write(){
std::string& tmpMsg = msgBuff[0];
boost::asio::async_write(
soc,
boost::asio::buffer(tmpMsg.c_str(), tmpMsg.size()),
strand.wrap(
boost::bind(&Connection::handleWrite,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
)
);
}
void handleWrite(const boost::system::error_code&, size_t s){
msgBuff.pop_front();
if (!msgBuff.empty())write();
}
void handleRead(const boost::system::error_code&, size_t s){
std::istream is(&buf);
std::string tmpMsg;
std::getline(is, tmpMsg);

(server->*serverHandler)(tmpMsg);
readMsg();
}


public:
typedef boost::shared_ptr<Connection> pointer;
static pointer createInstance(io_service& service){
return pointer(new Connection(service));
}

void init(Server* server, void(Server::*serverHandler)(std::string)){
this->server = server;
this->serverHandler = serverHandler;
writeMsg("hello\n");
readMsg();
}

void writeMsg(std::string msg){
strand.dispatch(boost::bind(&Connection::writeStranded, this, msg));
}

void readMsg(){
const char delim = '\n';
boost::asio::async_read_until(soc, buf, delim,
boost::bind(&Connection::handleRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

}

tcp::socket& getSocket(){
return soc;
}

};

class Server{
tcp::acceptor accept;
std::vector<Connection::pointer> connections;

public:
Server(io_service& io_service, int port = 23) :accept(io_service, tcp::endpoint(tcp::v4(), port)){
awaitConnection();
};


private:
void awaitConnection(){
Connection::pointer con = Connection::createInstance(accept .get_io_service());
accept.async_accept(con->getSocket(), boost::bind(&Server::conAcceptor, this, con, boost::asio::placeholders::error));
}
void conAcceptor(Connection::pointer con, const boost::system::error_code& err){
if (err)return;
con->init(this, &Server::msgHandler);
awaitConnection();
connections.push_back(con);
}
void msgHandler(std::string str){
for (Connection::pointer ptr : connections){
ptr->writeMsg(str+" by \"name\"\n");
}
}

};


int main(){
io_service io_service;
Server s(io_service);
io_service.run();
system("pause");

}

更新
原来 async_read 是在字符串后附加回车符,它被存储在 name 字符串中的定界符之前,每次我尝试让名字出现, 它前面的所有内容都会被后面的所有内容覆盖。有时回车会变乱并跳过名称前面的一些字符,这进一步复杂了此错误的搜索。

最佳答案

我让它运行起来了。我不得不为它写一个客户端......

在将其投入生产之前,您需要查看生命周期处理。正常的方式是连接对象在其绑定(bind)的处理程序中持有一个指向自身的 shared_ptr。

我使用了 c++14 lambda,因为我发现它们没有 boost::bind 繁重。

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


#include <iostream>
#include <vector>
#include <deque>
#include <iterator>

typedef boost::asio::io_service io_service;
typedef boost::asio::ip::tcp tcp;

class Server;

class Connection
: public boost::enable_shared_from_this<Connection>
{
io_service::strand strand;
tcp::socket soc;

// use double-buffering for the message sending
std::deque<std::string> sending, to_send;

boost::asio::streambuf buf;
Server *server;

void (Server::*serverHandler)(std::string);

private:
Connection(io_service& service)
: strand(service)
, soc(service)
{

}

void writeStranded(std::string msg)
{
assert(strand.running_in_this_thread()); // sanity check
to_send.push_back(std::move(msg));
maybe_write();

}

void maybe_write()
{
assert(strand.running_in_this_thread()); // sanity check
if (sending.empty() and not to_send.empty()) {
sending.swap(to_send);

// make a buffer sequence

auto buffers = std::vector<boost::asio::const_buffers_1>();
buffers.reserve(sending.size());
for (auto& data : sending) {
buffers.push_back(boost::asio::buffer(data));
}
boost::asio::async_write(soc, buffers,
strand.wrap([this](auto&& ec, size_t size)
{
this->sending.clear();
if (not ec) maybe_write();
}));
}
}

void handleRead(const boost::system::error_code&, size_t s)
{
std::istream is(&buf);
std::string tmpMsg;
std::getline(is, tmpMsg);

(server->*serverHandler)(tmpMsg);
readMsg();
}


public:
typedef boost::shared_ptr<Connection> pointer;

static pointer createInstance(io_service& service)
{
return pointer(new Connection(service));
}

void init(Server *server, void(Server::*serverHandler)(std::string))
{
this->server = server;
this->serverHandler = serverHandler;
writeMsg("hello\n");
readMsg();
}

void writeMsg(std::string msg)
{
strand.dispatch(boost::bind(&Connection::writeStranded, this, msg));
}

void readMsg()
{
const char delim = '\n';
boost::asio::async_read_until(soc, buf, delim,
boost::bind(&Connection::handleRead, this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));

}

tcp::socket& getSocket()
{
return soc;
}

};

class Server
{
tcp::acceptor accept;
std::vector<Connection::pointer> connections;

public:
Server(io_service& io_service, int port = 2333)
: accept(io_service, tcp::endpoint(tcp::v4(), port))
{
awaitConnection();
};


private:
void awaitConnection()
{
Connection::pointer con = Connection::createInstance(accept.get_io_service());
accept.async_accept(con->getSocket(),
boost::bind(&Server::conAcceptor, this, con, boost::asio::placeholders::error));
}

void conAcceptor(Connection::pointer con, const boost::system::error_code& err)
{
if (err)return;
con->init(this, &Server::msgHandler);
awaitConnection();
connections.push_back(con);
}

void msgHandler(std::string str)
{
for (Connection::pointer ptr : connections) {
ptr->writeMsg(str + " by \"name\"\n");
}
}

};

struct Client
{
using protocol = boost::asio::ip::tcp;

Client(boost::asio::io_service& exec)
: executor_(exec) {}


void run(int port)
{

resolver_.async_resolve(protocol::resolver::query("localhost", std::to_string(port)),
strand_.wrap([this](auto&& ec, auto iter)
{
std::cout << "resolve: " << ec.message() << std::endl;
if (not ec) start_connect(iter);
}));

}

void start_connect(protocol::resolver::iterator iter)
{
boost::asio::async_connect(socket_, iter,
strand_.wrap([this](auto&& ec, auto iter)
{
std::cout << "connect: " << ec.message() << std::endl;
if (not ec) {
this->start_reading();
auto data = std::make_shared<std::string>(
"The quick brown fox jumps over the lazy dog\n"
"Farmer bob has a cool tractor\n");
boost::asio::async_write(socket_, boost::asio::buffer(*data),
strand_
.wrap([data](auto&& ec, auto size)
{
std::cout << "written: "
<< size
<< std::endl;
}));
}
}));
}

void start_reading()
{
auto buffer = read_buffer_.prepare(1024);
socket_.async_read_some(read_buffer_.prepare(1024), [this](auto&& ec, auto size)
{
read_buffer_.commit(size);
std::istream is(std::addressof(read_buffer_));
std::string s;
while(std::getline(is, s)) {
std::cout << s << std::endl;
}
start_reading();
});

}

boost::asio::io_service& executor_;
boost::asio::io_service::strand strand_{executor_};
protocol::resolver resolver_{executor_};
protocol::socket socket_{executor_};
boost::asio::streambuf read_buffer_;
};

int main()
{
io_service io_service;
Server s(io_service);
Client c(io_service);
c.run(2333);
io_service.run();
system("pause");

}

输出(程序没有终止):

resolve: Undefined error: 0
connect: Undefined error: 0
written: 74
hello
The quick brown fox jumps over the lazy dog by "name"
Farmer bob has a cool tractor by "name"

关于c++ - boost::async_write 跳过部分字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45000263/

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