Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在一个线程中异步读取多个使用者的一个套接字_C++_Asynchronous_Networking_Boost Asio_Fibers - Fatal编程技术网

C++ 在一个线程中异步读取多个使用者的一个套接字

C++ 在一个线程中异步读取多个使用者的一个套接字,c++,asynchronous,networking,boost-asio,fibers,C++,Asynchronous,Networking,Boost Asio,Fibers,我正在实现一个连接多路复用器类,它封装单个连接,以便提供在其上创建所谓的流的能力。在一个物理连接上可以有几十个这样的流 通过该连接发送的消息由协议定义,可以是客户端从未看到的服务消息(拥塞控制等),也可以是数据消息-它们包含流的一些数据,其中一个在相应消息的头中定义 我在为流实现方法read时遇到了一个问题。它必须是阻塞的,但是是异步的,因此它返回一些值-数据读取或发生错误-但是请求本身必须是某种异步队列 为了实现异步网络IO,我们使用了Boost的async\u read-s、async\u

我正在实现一个连接多路复用器类,它封装单个连接,以便提供在其上创建所谓的
流的能力。在一个物理连接上可以有几十个这样的流

通过该连接发送的消息由协议定义,可以是客户端从未看到的服务消息(拥塞控制等),也可以是数据消息-它们包含流的一些数据,其中一个在相应消息的头中定义

我在为
实现方法
read
时遇到了一个问题。它必须是阻塞的,但是是异步的,因此它返回一些值-数据读取或发生错误-但是请求本身必须是某种异步队列

为了实现异步网络IO,我们使用了Boost的
async\u read
-s、
async\u write
-s等,以及从另一个库中获取的完成令牌。因此,对
MyConnection::undernative\u connection::read(size\u t)
的调用在我前面描述的术语中已经是异步的

我实现的一个解决方案是函数
MyConnection::processFrame()
,它从连接中读取、处理消息,如果是数据消息,则将数据放入相应流的缓冲区。该函数将在流的
read
循环中调用。但是,在这种情况下,可以有多个同时调用
async\u read
,即UB。此外,这意味着即使是服务消息也要等待,直到某个流想要读取数据,这也是不合适的

我提出的另一个解决方案是使用
future
-s,但正如我所检查的,他们的方法
wait/get
会阻塞整个线程(即使是延迟策略或成对承诺),这也必须避免

下面是一个简单的示例,其中只包含理解问题所需的方法。这是当前的实现,其中包含bug

struct低层连接{
///第三部分库的完成令牌-ufibers
产量&产量;
///asio插座
TcpSocket插座;
///完全异步(在一个线程中)方法
std::矢量读取(大小\u t字节){
std::向量res;
res.reserve(字节);
boost::asio::异步读取(socket、res、yield);
返回res;
}
}
结构MyConnection{
///页眉总是那个长度
constexpr uint32_t kHeaderSize=12;
///潜在联系
低电平连接;
///在连接启动的所有时间都在运行
void readLoop(){
while(connection.isActive()){
自动消息=连接读取(kHeaderSize);
if(msg.type==SERVICE){handleService(msg);return;}
//这是数据信息,请阅读其中的另一部分
自动数据=连接读取(消息数据大小);
//将数据放入流的缓冲区
streams.find(data.stream.id).buffer.put(data);
}
}
}
结构流{
缓冲区;
//还有异步阻塞方法
std::矢量读取(uint32_t字节){
//在完美的场景中,应该是这样的
async_wait([](){return buffer.size()>=bytes;});
//返回“bytes”大小的子缓冲区并将其删除
返回subbufer。。。
}
}

谢谢你以后的回答

请详细说明您提供的接口的要求,“阻塞,但异步”不清楚。使用流的代码是否使用回调/协同路由/光纤/?另外,在您的场景中,谁来管理执行器/光纤?“阻塞,但异步”没有多大意义,在术语上像ConyRadion一样查找。@Zulan。通过“阻塞,但异步”我的意思是,你调用这个方法,它直接返回一些值,没有回调,等等,但在后台,它使用光纤来管理多任务-因此没有创建线程,但一个线程仍然没有被阻塞,即使没有返回值-只需切换到另一个任务。执行器/光纤由
低层连接的底层实现管理
——当新连接从“另一端”到达时,它会被包装到光纤中。如果我们打开一个连接,同样,它是在光纤中打开的。请详细说明您提供的接口的要求,“阻塞,但异步”不清楚。使用流的代码是否使用回调/协同路由/光纤/?另外,在您的场景中,谁来管理执行器/光纤?“阻塞,但异步”没有多大意义,在术语上像ConyRadion一样查找。@Zulan。通过“阻塞,但异步”我的意思是,你调用这个方法,它直接返回一些值,没有回调,等等,但在后台,它使用光纤来管理多任务-因此没有创建线程,但一个线程仍然没有被阻塞,即使没有返回值-只需切换到另一个任务。执行器/光纤由
低层连接的底层实现管理
——当新连接从“另一端”到达时,它会被包装到光纤中。如果我们打开一个连接,同样,它是在光纤中打开的