首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何使用tokios异步TcpStream将贝维游戏连接到外部TCP服务器?

如何使用tokios异步TcpStream将贝维游戏连接到外部TCP服务器?
EN

Stack Overflow用户
提问于 2022-03-27 04:37:35
回答 1查看 469关注 0票数 2

我想发送事件之间的游戏客户端和服务器,我已经让它工作,但我不知道如何做它与贝维。

我依赖于使用tokios异步TcpStream,因为我必须能够使用stream.into_split()将流拆分为OwnedWriteHalfOwnedReadhalf

我的第一个想法是生成一个处理连接的线程,然后使用mpsc::channel将接收到的事件发送到队列中。

然后,我使用app.insert_resource(Queue)将这个队列包含到一个贝维资源中,并在游戏循环中从它中提取事件。

排队:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use tokio::sync::mpsc;

pub enum Instruction {
    Push(GameEvent),
    Pull(mpsc::Sender<Option<GameEvent>>),
}

#[derive(Clone, Debug)]
pub struct Queue {
    sender: mpsc::Sender<Instruction>,
}
impl Queue {
    pub fn init() -> Self {
        let (tx, rx) = mpsc::channel(1024);
        init(rx);
        Self{sender: tx}
    }
    pub async fn send(&self, event: GameEvent) {
        self.sender.send(Instruction::Push(event)).await.unwrap();
    }
    pub async fn pull(&self) -> Option<GameEvent> {
        println!("new pull");
        let (tx, mut rx) = mpsc::channel(1);
        self.sender.send(Instruction::Pull(tx)).await.unwrap();
        rx.recv().await.unwrap()
    }
}

fn init(mut rx: mpsc::Receiver<Instruction>) {
    tokio::spawn(async move {
        let mut queue: Vec<GameEvent> = Vec::new();

        loop {
            match rx.recv().await.unwrap() {
                Instruction::Push(ev) => {
                    queue.push(ev);
                }
                Instruction::Pull(sender) => {
                    sender.send(queue.pop()).await.unwrap();
                }
            }
        }
    });
}

但是由于所有这些都必须是异步的,所以我在同步游戏循环中阻塞了pull()函数。我使用futures-lite机箱来完成这个任务:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn event_pull(
    communication: Res<Communication>
) {
    let ev = future::block_on(communication.event_queue.pull());
    println!("got event: {:?}", ev);
}

这很好,但是大约5秒后整个程序就停止了,没有收到任何更多的事件。

看起来,future::block_on()确实会无限期地阻塞。

让主函数(在其中构建和运行bevy::prelude::App )成为异步tokio::main函数可能也是一个问题。

最好将异步TcpStream初始化和tokio::sync::mpsc::Sender以及Queue.pull封装到同步函数中,但我不知道如何做到这一点。

有人能帮忙吗?

如何繁殖

回购可以找到这里

只需编译serverclient,然后按相同的顺序运行。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-27 07:13:38

我用crossbeam::channel替换了每个crossbeam::channel,这可能是个问题,因为它确实会阻塞。

并手动初始化tokio运行时。

所以init代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
pub struct Communicator {
    pub event_bridge: bridge::Bridge,
    pub event_queue: event_queue::Queue,
    _runtime: Runtime,
}
impl Communicator {
    pub fn init(ip: &str) -> Self {
        let rt = tokio::runtime::Builder::new_multi_thread()
            .enable_io()
            .build()
            .unwrap();
    
        let (bridge, queue, game_rx) = rt.block_on(async move {
            let socket = TcpStream::connect(ip).await.unwrap();
            let (read, write) = socket.into_split();
            let reader = TcpReader::new(read);
            let writer = TcpWriter::new(write);
        
            let (bridge, tcp_rx, game_rx) = bridge::Bridge::init(); 
            reader::init(bridge.clone(), reader);
            writer::init(tcp_rx, writer);
        
            let event_queue = event_queue::Queue::init();
        
            return (bridge, event_queue, game_rx);
        });
    
        // game of game_rx events to queue for game loop
        let eq_clone = queue.clone();
        rt.spawn(async move {
            loop {
                let event = game_rx.recv().unwrap(); 
                eq_clone.send(event);
            }
        });
    
        Self {
            event_bridge: bridge,
            event_queue: queue,
            _runtime: rt,
        }
    }
}

main.rs看起来是这样的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn main() {
    let communicator = communication::Communicator::init("0.0.0.0:8000");

    communicator.event_bridge.push_tcp(TcpEvent::Register{name: String::from("luca")});

    App::new()
        .insert_resource(communicator)
        .add_system(event_pull)
        .add_plugins(DefaultPlugins)
        .run();
}

fn event_pull(
    communication: Res<communication::Communicator>
) {
    let ev = communication.event_queue.pull();
    if let Some(ev) = ev {
        println!("ev");
    }
}

也许会有更好的解决办法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71636383

复制
相关文章
WCF技术剖析之二:再谈IIS与ASP.NET管道
在2007年9月份,我曾经写了三篇详细介绍IIS架构和ASP.NET运行时管道的文章,深入介绍了IIS 5.x与IIS 6.0HTTP请求的监听与分发机制,以及ASP.NET运行时管道对HTTP请求的处理流程:
莫问今朝
2019/02/25
1.2K0
WCF技术剖析之二:再谈IIS与ASP.NET管道
在2007年9月份,我曾经写了三篇详细介绍IIS架构和ASP.NET运行时管道的文章,深入介绍了IIS 5.x与IIS 6.0HTTP请求的监听与分发机制,以及ASP.NET运行时管道对HTTP请求的处理流程: [原创]ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI [原创]ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline - Part I [原创]ASP.NET Process Model之二:ASP.N
蒋金楠
2018/01/16
1.6K0
WCF技术剖析之二:再谈IIS与ASP.NET管道
ASP.NET 管道
序号 名称 说明 1 BeginRequest ASP.NET开始处理的第一个时间,表示处理的开始 2 AuthenticateRequest 验证请求,一般用来取得请求的用户信息 3 PostAuthenticateRequest 已经获取请求的用户信息 4 AuthorizeRequest 授权,一般用来检查用户的请求是否获得权限 5 PostAuthorizeRequest 用户请求已经得到授权 6 ResolveRequestCache 获取以前处理缓存的处理结果,如果以前缓存过,那么不必再进行请求
莫问今朝
2019/02/25
1.8K0
ASP.NET是如何在IIS下工作的
ASP.NET与IIS是紧密联系的,由于IIS6.0与IIS7.0的工作方式的不同,导致ASP.NET的工作原理也发生了相应的变化。 IIS6(IIS7的经典模式)与IIS7的集成模式的不同 IIS6
古时的风筝
2018/01/08
3K0
ASP.NET是如何在IIS下工作的
ASP.NET Core管道深度剖析(3):管道是如何处理HTTP请求的?
我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成,所以从总体设计来讲是非常简单的,但是就具体的实现来说,由于其中涉及很多对象的交互,我想很少人能够地把它弄清楚。为了让读者朋友们能够更加容易地理解管道处理HTTP请求的总体流程,我们根据真实管道的实现原理再造了一个“模拟管道”并在此管道上开发了一个发布图片的应用,这篇文章旨在为你讲述管道是如何处理HTTP请求的 目录 一、HttpApplication     FeatureCollection     HostingAppli
蒋金楠
2018/01/15
1.4K0
ASP.NET Core管道深度剖析(3):管道是如何处理HTTP请求的?
ASP.NET Core管道详解[6]: ASP.NET Core应用是如何启动的?[下篇]
要承载一个ASP.NET Core应用,只需要将GenericWebHostService服务注册到承载系统中即可。但GenericWebHostService服务具有针对其他一系列服务的依赖,所以在注册该承载服务之前需要先完成对这些依赖服务的注册。针对GenericWebHostService及其依赖服务的注册是借助GenericWebHostBuilder对象来完成的。
蒋金楠
2020/12/07
2.4K0
ASP.NET Core管道详解[5]: ASP.NET Core应用是如何启动的?[上篇]
我们知道ASP.NET Core应用的请求处理管道是由一个IServer对象和IHttpApplication对象构成的。我们可以根据需要注册不同类型的服务器,但在默认情况下,IHttpApplication是一个HostingApplication对象。一个HostingApplication对象由指定的RequestDelegate对象来完成所有的请求处理工作,而后者代表所有中间件按照注册的顺序串联而成的委托链。所有的这一切都被GenericWebHostService整合在一起,在对这个承载Web应用的服务做进一步介绍之前,下面先介绍与它相关的配置选项。[本文节选自《ASP.NET Core 3框架揭秘》第13章, 更多关于ASP.NET Core的文章请点这里]
蒋金楠
2020/12/03
7670
模块和处理程序之通过HttpModule和HttpHandler拦截入站HTTP请求执行指定托管代码模块
1、简介 大多数情况下,作为一个asp.net web开发对整个web应用程序的控制是十分有限的,我们的控制往往只能做到对应用程序(高层面)的基本控制。但是,很多时候,我们需要能够低级层面进行交互,例如:Web服务器如何处理入站的出站的Http请求,这就需要找到与iis交互的方法! 在Asp.Net推出之前,为了获得IIS这个级别的控制,必须创建和扩展ISAPI扩展或过滤器,但是如果使用这个方法,必须具备C和C++的知识,并需要知道如何创建本机的Win32 Dll,所以为了解决这个问题,ASP.NET提供了
郑小超.
2018/01/26
1.2K0
IIS部署asp.net mvc网站
iis配置简单的ASP.NET MVC网站 编译器:VS 2013 本地IIS:IIS 7 操作系统:win 7 MVC版本:ASP.NET MVC4 sql server版本: 2008 r2
Ryan_OVO
2023/10/18
4440
IIS部署asp.net mvc网站
ASP.NET Core管道深度剖析(4):管道是如何建立起来的?
在《管道是如何处理HTTP请求的?》中,我们对ASP.NET Core的请求处理管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的。这样一个管道由一个服务器和一个HttpApplication构成,前者负责监听请求并将接收的请求传递给给HttpAppkication对象处理,后者则将请求处理任务委托给注册的中间件来完成。中间件的注册是通过ApplicationBuilder对象来完成的,所以我们先来了解一下这究竟是个怎样的对象。 目录 Applicati
蒋金楠
2018/01/15
9230
ASP.NET Core管道深度剖析(4):管道是如何建立起来的?
[原创-总结]WCF技术剖析系列总结篇
近半年以来,一直忙于我的第一本WCF专著《WCF技术剖析》的写作,一直无暇管理自己的Blog。到目前为止《WCF技术剖析(卷1)》的写作暂告一段落,初步预计于下个月由武汉博文视点出版。在《WCF技术剖析》写作期间,对WCF又有了新的感悟,为此以书名开始本人的第三个WCF系列。本系列的目的在于对《WCF技术剖析》的补充,会对书中的一些内容进行展开讲述,同时会囊括很多由于篇幅的原因忍痛割弃的内容。 1、通过一个ASP.NET程序模拟WCF基础架构 本系列的第一篇,我将会对WCF的基本架构作一个大致的讲解。不过,
蒋金楠
2018/01/16
1K0
IIS 5.x与ASP.NET
我们先来看看IIS 5.x是如何处理基于ASP.NET资源(比如.aspx,.asmx等)请求的,整个过程基本上可以通过图1体现。
莫问今朝
2019/02/25
2.8K0
【译】在ASP.Net和IIS中删除不必要的HTTP响应头
   每次当浏览器向Web服务器发起一个请求的时,都会伴随着一些HTTP头的发送.而这些HTTP头是用于给Web服务器提供一些额外信息以便于处理请求。比如说吧。如果浏览器支持压缩功能,则浏览器会发送Accept-Encoding HTTP头,这样一来服务器便知道浏览器可以使用哪种压缩算法。还有任何在上一次传输中服务端设置的cookies也会通过Cookies HTTP头来回传到服务器,浏览器还会发送用于让服务端知道客户使用的是何种浏览器(IE,火狐,Safari等),浏览器版本,操作系统以及其他相关信息的User-Agent HTTP头。
跟着阿笨一起玩NET
2018/09/20
3.1K0
【译】在ASP.Net和IIS中删除不必要的HTTP响应头
ASP.NET Core 中的管道机制
在开始之前,我们需要明确的一个概念是,在 Web 程序中,用户的每次请求流程都是线性的,放在 ASP.NET Core 程序中,都会对应一个 请求管道(request pipeline),在这个请求管道中,我们可以动态配置各种业务逻辑对应的 中间件(middleware),从而达到服务端可以针对不同用户做出不同的请求响应。在 ASP.NET Core 中,管道式编程是一个核心且基础的概念,它的很多中间件都是通过 管道式 的方式来最终配置到请求管道中的,所以理解这里面的管道式编程对我们编写更加健壮的 DotNetCore 程序相当重要。
梁规晓
2019/07/31
1.3K0
ASP.NET Core 中的管道机制
ASP.NET Core管道深度剖析(1):采用管道处理HTTP请求
之所以称ASP.NET Core是一个Web开发平台,源于它具有一个极具扩展性的请求处理管道,我们可以通过这个管道的定制来满足各种场景下的HTTP处理需求。ASP. NET Core应用的很多特性,比如路由、认证、会话、缓存等,也同时定制消息处理管道来实现的。我们甚至可以通过管道定制在ASP.NET Core平台上创建我们自己的Web框架,实际上MVC和SingalR这两个重要的Web框架也是采用这样的方式创建的。 HTTP协议自身的特性决定了任何一个Web应用的工作方式都是监听、接收并处理HTTP请求,
蒋金楠
2018/01/15
8500
ASP.NET Core管道深度剖析(1):采用管道处理HTTP请求
ASP.NET MVC5请求管道和生命周期
请求管道是一些用于处理HTTP请求的模块组合,在ASP.NET中,请求管道有两个核心组件:IHttpModule和IHttpHandler。所有的HTTP请求都会进入IHttpHandler,有IHttpHandler进行最终的处理,而IHttpModule通过订阅HttpApplication对象中的事件,可以在IHttpHandler对HTTP请求进行处理之前对请求进行预处理或IHttpHandler对HTTP请求处理之后进行再次处理。
雪飞鸿
2018/09/05
1.7K0
ASP.NET MVC5请求管道和生命周期
ASP.NET Core 中的管道机制
在开始之前,我们需要明确的一个概念是,在 Web 程序中,用户的每次请求流程都是线性的,放在 ASP.NET Core 程序中,都会对应一个 请求管道(request pipeline),在这个请求管道中,我们可以动态配置各种业务逻辑对应的 中间件(middleware),从而达到服务端可以针对不同用户做出不同的请求响应。在 ASP.NET Core 中,管道式编程是一个核心且基础的概念,它的很多中间件都是通过 管道式 的方式来最终配置到请求管道中的,所以理解这里面的管道式编程对我们编写更加健壮的 DotNetCore 程序相当重要。
AI.NET 极客圈
2019/07/30
1.1K0
ASP.NET Core 中的管道机制
MVC5 - ASP.NET Identity登录原理 - Claims-based认证和OWIN
在Membership系列的最后一篇引入了ASP.NET Identity,看到大家对它还是挺感兴趣的,于是来一篇详解登录原理的文章。本文会涉及到Claims-based(基于声明)的认证,我们会详细介绍什么是Claims-based认证,它与传统认证方式的区别,以及它的特点。同时我们还会介绍OWIN (Open Web Interface for .NET) 它主要定义了Web Server 和Web Application之间的一些行为,然后实现这两个组件的解耦(当然远不止这么点东西,我相信OWIN马
用户1153966
2018/03/14
2.7K0
MVC5 - ASP.NET Identity登录原理 - Claims-based认证和OWIN
Http请求处理流程
我查阅过不少Asp.Net的书籍,发现大多数作者都是站在一个比较高的层次上讲解Asp.Net。他们耐心、细致地告诉你如何一步步拖放控件、设置控件属性、编写CodeBehind代码,以实现某个特定的功能。
张子阳
2018/09/27
1.3K0
Http请求处理流程
IIS7报500.23错误的原因分析及解决方法
  今天公司终端上有一个功能打开异常,报500错误,我用Fiddler找到链接,然后在IE里打开,报500.23错误:检测到在集成的托管管道模式下不适用的ASP.NET设置。后台是一个IIS7和tomcat7集成的环境,此处记录一下。
会长君
2023/04/26
8340

相似问题

将C语言转换为mips程序集

12

将C语言转换为MIPS程序集

28

将C语言转换为MIPS64程序集

21

将MIPS程序集转换为C

12

将C转换为MIPS程序集

11
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文