C++ 在boost::asio basic\u stream\u socket::async\u read\u some处理程序中仅使用部分数据
我是boost::asio的新手,所以我的问题可能是愚蠢的-如果是这样的话,很抱歉。 我正在使用keepalive编写异步服务器应用程序(在一个连接上可以发送多个请求) 连接处理例程很简单: 在循环中:C++ 在boost::asio basic\u stream\u socket::async\u read\u some处理程序中仅使用部分数据,c++,boost,boost-asio,C++,Boost,Boost Asio,我是boost::asio的新手,所以我的问题可能是愚蠢的-如果是这样的话,很抱歉。 我正在使用keepalive编写异步服务器应用程序(在一个连接上可以发送多个请求) 连接处理例程很简单: 在循环中: 使用套接字->异步读取(缓冲区、处理程序)计划读取请求 从处理程序使用异步_write调度写入响应 我面临的问题是 传递给async_read_的处理程序有些被io_服务线程调用,缓冲区实际上可能包含比单个请求更多的数据(例如,客户端发送的下一个请求的一部分) 我现在不想(如果它只是请求的一
- 使用套接字->异步读取(缓冲区、处理程序)计划读取请求
- 从处理程序使用异步_write调度写入响应
boost::asio中是否存在这种可能性,或者我是否必须将剩余数据存储在一旁,并使用额外的代码自行处理。当使用可靠且有序的传输(如TCP)时,解决此问题的一种方法是:
在使用可靠且有序的传输(如TCP)时,解决此问题的一种方法是:
如果您知道消息的长度是固定的,可以执行以下操作:
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
void
Connection::readMore()
{
if (m_connected)
{
// Asynchronously read some data from the connection into the buffer.
// Using shared_from_this() will prevent this Connection object from
// being destroyed while data is being read.
boost::asio::async_read(
m_socket,
boost::asio::buffer(
m_readMessage.getData(),
MessageBuffer::MESSAGE_LENGTH
),
boost::bind(
&Connection::messageBytesRead,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
),
boost::bind(
&Connection::handleRead,
shared_from_this(),
boost::asio::placeholders::error
)
);
}
}
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
std::size_t
Connection::messageBytesRead(const boost::system::error_code& _errorCode,
std::size_t _bytesRead)
{
return MessageBuffer::MESSAGE_LENGTH - _bytesRead;
}
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
void
Connection::handleRead(const boost::system::error_code& _errorCode)
{
if (!_errorCode)
{
/// Do something with the populated m_readMessage here.
readMore();
}
else
{
disconnect();
}
}
读取完整消息后,
messageBytesRead
回调将向boost::asio::async\u read
发出指示。此代码段是从运行代码的现有连接
对象中提取的,因此我知道它是有效的…如果您知道消息将具有固定长度,可以执行以下操作:
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
void
Connection::readMore()
{
if (m_connected)
{
// Asynchronously read some data from the connection into the buffer.
// Using shared_from_this() will prevent this Connection object from
// being destroyed while data is being read.
boost::asio::async_read(
m_socket,
boost::asio::buffer(
m_readMessage.getData(),
MessageBuffer::MESSAGE_LENGTH
),
boost::bind(
&Connection::messageBytesRead,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
),
boost::bind(
&Connection::handleRead,
shared_from_this(),
boost::asio::placeholders::error
)
);
}
}
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
std::size_t
Connection::messageBytesRead(const boost::system::error_code& _errorCode,
std::size_t _bytesRead)
{
return MessageBuffer::MESSAGE_LENGTH - _bytesRead;
}
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
void
Connection::handleRead(const boost::system::error_code& _errorCode)
{
if (!_errorCode)
{
/// Do something with the populated m_readMessage here.
readMore();
}
else
{
disconnect();
}
}
读取完整消息后,
messageBytesRead
回调将向boost::asio::async\u read
发出指示。此代码段是从运行代码的现有连接对象中提取的,因此我知道它是有效的…我想您要查找的是
基本上,您可以将种子streambuf作为char*进行检查,阅读您认为合适的内容,然后告知消费(金额)
实际处理了多少内容
将HTTP头解析为客户端的工作代码示例:
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <string>
namespace asio = boost::asio;
std::string LINE_TERMINATION = "\r\n";
class Connection {
asio::streambuf _buf;
asio::ip::tcp::socket _socket;
public:
Connection(asio::io_service& ioSvc, asio::ip::tcp::endpoint server)
: _socket(ioSvc)
{
_socket.connect(server);
_socket.send(boost::asio::buffer("GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"));
readMore();
}
void readMore() {
// Allocate 13 bytes space on the end of the buffer. Evil prime number to prove algorithm works.
asio::streambuf::mutable_buffers_type buf = _buf.prepare(13);
// Perform read
_socket.async_read_some(buf, boost::bind(
&Connection::onRead, this,
asio::placeholders::bytes_transferred, asio::placeholders::error
));
}
void onRead(size_t read, const boost::system::error_code& ec) {
if ((!ec) && (read > 0)) {
// Mark to buffer how much was actually read
_buf.commit(read);
// Use some ugly parsing to extract whole lines.
const char* data_ = boost::asio::buffer_cast<const char*>(_buf.data());
std::string data(data_, _buf.size());
size_t start = 0;
size_t end = data.find(LINE_TERMINATION, start);
while (end < data.size()) {
std::cout << "LINE:" << data.substr(start, end-start) << std::endl;
start = end + LINE_TERMINATION.size();
end = data.find(LINE_TERMINATION, start);
}
_buf.consume(start);
// Wait for next data
readMore();
}
}
};
int main(int, char**) {
asio::io_service ioSvc;
// Setup a connection and run
asio::ip::address localhost = asio::ip::address::from_string("127.0.0.1");
Connection c(ioSvc, asio::ip::tcp::endpoint(localhost, 80));
ioSvc.run();
}
#包括
#包括
#包括
#包括
名称空间asio=boost::asio;
std::字符串行\u终止=“\r\n”;
类连接{
asio::streambuf buf;
asio::ip::tcp::socket _socket;
公众:
连接(asio::io_服务和ioSvc,asio::ip::tcp::端点服务器)
:_插座(ioSvc)
{
_socket.connect(服务器);
_send(boost::asio::buffer(“GET/HTTP/1.1\r\nHost:localhost\r\n连接:close\r\n\r\n”);
readMore();
}
void readMore(){
//在缓冲区的末尾分配13字节的空间。邪恶的素数证明算法是有效的。
asio::streambuf::可变缓冲区类型buf=\u buf.prepare(13);
//执行读取
_socket.async\u read\u some(buf,boost::bind(
&连接::onRead,这个,
asio::占位符::已传输的字节数,asio::占位符::错误
));
}
void onRead(大小读取,常量boost::系统::错误代码和ec){
如果((!ec)&(读取>0)){
//标记缓冲区实际读取的数据量
_提交(读);
//使用一些难看的解析来提取整行。
const char*data=boost::asio::buffer\u cast(_buf.data());
std::字符串数据(data_u,buf.size());
大小\u t开始=0;
size\u t end=data.find(行终止,开始);
while(end 我想你要找的是
基本上,您可以将种子streambuf作为char*进行检查,阅读您认为合适的内容,然后告知消费(金额)
实际处理了多少内容
将HTTP头解析为客户端的工作代码示例:
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <string>
namespace asio = boost::asio;
std::string LINE_TERMINATION = "\r\n";
class Connection {
asio::streambuf _buf;
asio::ip::tcp::socket _socket;
public:
Connection(asio::io_service& ioSvc, asio::ip::tcp::endpoint server)
: _socket(ioSvc)
{
_socket.connect(server);
_socket.send(boost::asio::buffer("GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"));
readMore();
}
void readMore() {
// Allocate 13 bytes space on the end of the buffer. Evil prime number to prove algorithm works.
asio::streambuf::mutable_buffers_type buf = _buf.prepare(13);
// Perform read
_socket.async_read_some(buf, boost::bind(
&Connection::onRead, this,
asio::placeholders::bytes_transferred, asio::placeholders::error
));
}
void onRead(size_t read, const boost::system::error_code& ec) {
if ((!ec) && (read > 0)) {
// Mark to buffer how much was actually read
_buf.commit(read);
// Use some ugly parsing to extract whole lines.
const char* data_ = boost::asio::buffer_cast<const char*>(_buf.data());
std::string data(data_, _buf.size());
size_t start = 0;
size_t end = data.find(LINE_TERMINATION, start);
while (end < data.size()) {
std::cout << "LINE:" << data.substr(start, end-start) << std::endl;
start = end + LINE_TERMINATION.size();
end = data.find(LINE_TERMINATION, start);
}
_buf.consume(start);
// Wait for next data
readMore();
}
}
};
int main(int, char**) {
asio::io_service ioSvc;
// Setup a connection and run
asio::ip::address localhost = asio::ip::address::from_string("127.0.0.1");
Connection c(ioSvc, asio::ip::tcp::endpoint(localhost, 80));
ioSvc.run();
}
#包括
#包括
#包括
#包括
名称空间asio=boost::asio;
std::字符串行\u终止=“\r\n”;
类连接{
asio::streambuf buf;
asio::ip::tcp::socket _socket;
公众:
连接(asio::io_服务和ioSvc,asio::ip::tcp::端点服务器)
:_插座(ioSvc)
{
_socket.connect(服务器);
_send(boost::asio::buffer(“GET/HTTP/1.1\r\nHost:localhost\r\n连接:close\r\n\r\n”);
readMore();
}
void readMore(){
//在缓冲区的末尾分配13字节的空间。邪恶的素数证明算法是有效的。
asio::streambuf::可变缓冲区类型buf=\u buf.prepare(13);
//执行读取
_socket.async\u read\u some(buf,boost::bind(
&连接::onRead,这个,
asio::占位符::已传输的字节数,asio::占位符::错误
));
}
void onRead(大小读取,常量boost::系统::错误代码和ec){
如果((!ec)&(读取>0)){
//标记缓冲区实际读取的数据量
_提交(读);
//使用一些难看的解析来提取整行。
const char*data=boost::asio::buffer\u cast(_buf.data());
std::字符串数据(data_u,buf.size());
大小\u t开始=0;
size\u t end=data.find(行终止,开始);
while(end 不幸的是,这是不可行的,因为协议是固定的,我不能修改它:(@losipiuk,所以你是说当前形式的协议不包含任何元数据