使用sunshine和moonlight实现远程游戏串流

过年回家想要打游戏,但是苦于家里没有电脑,又没办法把电脑搬回去,于是想到了使用串流的方式。

实现串流的软件有多种:

  1. moonlight。因为仅实现了 NVIDIA 的游戏串流协议,所以只支持 N 卡。
  2. Steam Link。支持 steam 的游戏。
  3. Sunshine。支持 AMD, Intel, 和 Nvidia 三家的显卡。而且支持使用 Moonlight 作为客户端。开源。
  4. Parsec。其实是一个远程桌面的商业解决方案,不仅仅能用来打游戏。需要注册账号且闭源。

因为使用的是 A 卡,而且玩的不只是 steam 游戏,经过综合的考虑,选择了 Sunshine 作为串流工具。

Sunshine 的安装

首先需要在官网下载 Sunshine,安装后设置开机启动。

如果启动时命令行窗口提示

Terminate called after throwing an instance of 'std::range_error'
  what():  wstring_convert::from_bytes

则需要通过 Win+S 输入【区域】并进入区域设置,点击【管理】标签页,然后点击【更改系统区域设置】,勾选【Beta 版:使用 Unicode UTF-8 提供全球语言支持】,重启电脑。

请添加图片描述

ipv6

想要从外网访问主机,有两种方式,一种是公网 ip,一种是内网穿透。

公网的 ipv4 需要向运营商申请,因为 ipv4 稀缺的原因,所以很难申请到。但是 ipv6 可以让全球每台设备都拥有一个可访问的公网地址。

首先访问 IPv6 测试 测试是否支持 ipv6,如果显示 DNS 服务器已经配置 IPv6,说明营运商已经接入 ipv6,这时候只需要找到路由器,打开 ipv6 开关便可。
请添加图片描述

现在大多数运营商都已经接入 ipv6,除了
个别 (说的就是广电网络),没有接入的话,需要打电话给运营商开通。

连接上 ipv6 网络后,可以通过访问 ipv6 网站获取可访问的外网 ipv6 地址,也可以通过 ipconfig /all 命令获取。

请添加图片描述

DDNS

运营商出于安全考虑,并不会给固定的 ipv6 地址,每次拨号后或者电脑重启后,ip 地址都会改变,导致每次都要手动获取当前的 ipv6 地址。一种解决办法是使用 DDNS(动态域名解析),将 ip 地址映射到固定的域名地址,并检测每次 ip 地址的变更,重新进行映射。部分路由器会提供 DDNS 功能,我们需要注册一个路由器支持的 DDNS 提供商的账号。

下面以 no-ip 为例。

先去官网注册一个账号 Free Dynamic DNS No-IP,然后新建一个域名,Record Type 选择 ipv6,再把主机的 ipv4 和 ipv6 地址填上去。
请添加图片描述

新建好域名后,把账号信息填到路由器上的 DDNS 功能上,便可使用。

如果路由器不支持 DDNS 咋办?这就需要使用脚本动态监听 ip 地址的更改,并修改映射。

下面是一个使用 python 实现一个定时获取本机 ipv6 地址。然后通过 no-ip 的 api 修改映射的脚本。

import socket
import base64
import os
import re
import time

class netParam:
    def __init__(self):
        self.host = "xxx"
        self.usrname = "xxx"
        self.passwd = "xxx"
        self.domain = "xxx"
        self.timeval = 10 * 60
        self.server_port = 80

def getIPv6Address():
    host_ipv6=[]
    ips=socket.getaddrinfo(socket.gethostname(),80)
    for ip in ips:
        if ip[4][0].startswith('24'):
	    # 2408 中国联通
	    # 2409 中国移动
	    # 240e 中国电信
            return ip[4][0]

def getip(domain):
    address = socket.getaddrinfo(domain, 'http')
    return address[0][4][0]
  

if __name__ == "__main__":
    param = netParam()
    tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 不经过WAIT_TIME,直接关闭
    tcp_sock.setblocking(False)                                     # 设置非阻塞编程
    tcp_sock.settimeout(1)
    link_statu = False
    send_data_len = 0
    old_ipv6addr = ""
    fisrt_flag = True

    # 按协议,对usrname:passwd进行base64编码
    raw_key = param.usrname + ":" + param.passwd
    print("raw key: " + raw_key)
    encode_key = base64.b64encode(raw_key.encode("utf-8"))
    encode_key = str(encode_key)[2:len(str(encode_key)) - 1]
    print("encode key: " + encode_key)

    #构造请求头部的内容,由于本机ip可能变化,因此这里没有直接把GET方法写进去,而是放在循环体中做
    requestParam = ""
    requestParam += "Host: dynupdate.no-ip.com\r\n"
    requestParam += "Authorization: Basic " + encode_key + "\r\n"
    requestParam += "User-Agent: None\r\n\r\n"
    print("request:\n" + requestParam)

    while(True):
        # 每次运行等待timeval(此处是5分钟)的间隔,避免频繁更新
        if (True != fisrt_flag):
            time.sleep(param.timeval)
        fisrt_flag = False

        # 获取ipv6地址,若地址没有发生改变,则不上报更新
        ipv6addr = getIPv6Address()
        if (0 != len(ipv6addr)):
            print("ipv6 addr: " + ipv6addr)
            if (ipv6addr == old_ipv6addr):
                print("ip not change, continue")
                continue
                
        # 构造请求的头部GET方法内容
        requestHead = "GET "
        requestHead += "/nic/update?hostname=" + param.domain + "&myip=" + ipv6addr + " HTTP/1.1\r\n"

        # 建立tcp连接
        if (False == link_statu):
            server_ip = getip(param.host)
            print("server ip is :" + server_ip)
            try:
                tcp_sock.connect((server_ip, param.server_port))
                print("connect server success")
                link_statu = True
            except Exception as err:
                print("connect server failed, exception:", err)
                continue

        # 发送数据
        send_data = requestHead + requestParam
        send_data_len = 0
        while send_data_len < len(send_data):
            time.sleep(0.1)
            try:
                send_data_len += tcp_sock.send(send_data[send_data_len:].encode())
                print("send " + str(send_data_len) + " data")
            except Exception as err:
                print("send data error, exception: ", err)
                print("close tcp socket")
                tcp_sock.close()
                link_statu = False
                break

        if (send_data_len != len(send_data)):
            continue
        print("send data:" + send_data)
        # 检查结果,更新成功则把当前ip记录为旧ip
        if (True == link_statu):
            try:
                recv_data = tcp_sock.recv(2048)
                print("server reply:\n" + str(recv_data))
            except Exception as err:
                print("recv data error, exception: ", err)
                tcp_sock.close()
                link_statu = False

        if (-1 != str(recv_data).find("HTTP/1.1 200 OK")):
            old_ipv6addr = ipv6addr
            print("update ip success")
    print("end")

最好将脚本设置开机启动。

防火墙

在成功设置域名访问后,会发现依旧无法访问主机,这是因为路由器和主机上都设置了防火墙,阻止外来网络的恶意访问。所以我们需要关闭路由器的防火墙,设置 window 防火墙开放 moonlight 的端口。端口为:

  • TCP: 47984, 47989, 48010
  • UDP: 47998-48000, 48002, 48010

开放 window 的防火墙的特定端口,首先 win 键搜索“高级安全 Windows Defender 防火墙”,选择入站规则 ->新建规则 ->端口。

请添加图片描述

选择 UDP 或 TCP,输入特定端口。
请添加图片描述

到此,便可从外网访问到内网主机。

内网穿透

但如果控制端和被控制端任何一方不存在 ipv6,则只能使用内网穿透,内网穿透可以使用 zerotier,使用办法也很简单,注册一个账号,然后新建一个网络,得到一个网络 ID,分别下载 window 和安卓端的软件,添加网络 ID,便可以使用。在网络的设置页面能看到给成员分配的 ipv4 地址,可以通过这个 ipv4 地址互相访问。

智能插座与主板来电启动

解决了上述问题后,远程问题是解决了,但是电脑不可能一直开着,这时候可以使用智能插座或者开机棒,如果是小米智能插座,可以直接连 wifi,如果是小米智能插板,则另外需要一个网关。特别需要注意的是,在电脑关机后,一定要多等几分钟确定功率为 0 后再关闭插座,防止电脑突然断电。

然后设置主板的来电启动,这个需要参考不同主板的设置。

显卡欺骗器

还有问题就是,显示器关闭状态下,显卡是不会工作的,这会导致串流时显示黑屏,解决办法是购买一个 HDMI 显卡欺骗器,或者网上下载一个虚拟现实器的软件,从而实现显示器关闭后,显卡也能正常工作。

最后

准备工作做好后,最后便是下载 moonlight手机端,通过域名连上电脑,开开心心打游戏。

建议最好是把向日葵也设置开启启动,防止出现问题时也能远程连接上电脑。

参考:

  1. Sunshine error at launch · Issue #1446 · LizardByte/Sunshine · GitHub
  2. GitHub - LizardByte/Sunshine: Self-hosted game stream host for Moonlight.
  3. DDNS No-IP自动更新IPv6地址的的Python脚本-CSDN博客
  4. No-ip ddns动态域名解析 - 简书
  5. create-hostname-ipv6-address-aaaa-record-support-question-day
  6. ZeroTier | Global Area Networking

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/431264.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第五十回 插翅虎枷打白秀英 美髯公误失小衙内-mayfly-go:web 版 linux、数据库等管理平台

晁盖宋江和吴用到山下迎接雷横上山&#xff0c;宋江邀请雷横入伙&#xff0c;雷横以母亲年事已高为由拒绝了。 雷横回到郓城&#xff0c;听李小二说从东京新来了个表演的叫白秀英&#xff0c;吹拉弹唱跳&#xff0c;样样精通&#xff0c;于是雷横和李小二一起到戏院去看演出。…

什么是AJAX?它的运用场景有哪些?

文章目录 前言一、什么是AJAX二、AJAX原理是什么三、为什么需要AJAX四、AJAX的使用五、AJAX的应用场景 前言 AJAX 即 Asynchronous Javascript And XML&#xff08;异步JavaScript和XML&#xff09;&#xff0c;是指一种创建交互式网页应用的网页开发技术。 AJAX 是一种用于创…

首尔之春在线资源最新电影1080p高清

打开下面这个链接就可以看到 首尔之春在线资源最新电影1080p高清 如果链接打不开&#xff0c;就复制下面的网址到浏览器打开 https://www.zhufaka.cn/liebiao/A09504AE3BF8BD06 用阿里云盘下载&#xff0c;下载完成之后&#xff0c;用迅雷播放 首尔之春在线资源最新电影10…

NVMe管理命令为何不用SGL?-2

在IO数据传输中&#xff0c;是否选择SGL可以根据自身场景的需要。SGL提供的是一种高效且灵活的方式来描述非连续的内存区域&#xff0c;这对于现代高性能存储系统至关重要&#xff0c;尤其是在处理大数据块或者随机小I/O操作时具有明显优势&#xff1a; 高效的数据传输&#xf…

【OpenGL编程手册09】颜色和光照

目录标题 一、说明二、物理概念三、OpenGL处理办法四、创建一个光照场景 一、说明 在前面的教程中我们已经简要提到过该如何在OpenGL中使用颜色(Color)&#xff0c;但是我们至今所接触到的都是很浅层的知识。本节我们将会更深入地讨论什么是颜色&#xff0c;并且还会为接下来的…

Minio容器化部署并整合SpringBoot

1、启动minio容器 docker run -p 9000:9000 -p 9090:9090 --name minio -d --restartalways -e MINIO_ACCESS_KEYminio -e MINIO_SECRET_KEYminio -v /usr/local/minio/data:/data -v /usr/local/minio/config:/root/.minio minio/minio server /data --console-addr…

文件操作与IO(3) 文件内容的读写——数据流

目录 一、流的概念 二、字节流代码演示 1、InputStream read方法 第一个没有参数的版本&#xff1a; 第二个带有byte数组的版本&#xff1a; 第三个版本 搭配Scanner的使用 2、OutputStream write方法 第一个版本&#xff1a; 第二个写入整个数组版本&#xff1a; …

16 PyTorch 神经网络基础【李沐动手学深度学习v2】

要想直观地了解块是如何工作的&#xff0c;最简单的方法就是自己实现一个。 在实现我们自定义块之前&#xff0c;我们简要总结一下每个块必须提供的基本功能。 将输入数据作为其前向传播函数的参数。 通过前向传播函数来生成输出。请注意&#xff0c;输出的形状可能与输入的形…

python一张大图找小图的个数

python一张大图找小图的个数 一、背景 有时候我们在浏览网站时&#xff0c;发现都是前端搞出来的一张张图&#xff0c;我们只能用盯住屏幕的小眼睛看着&#xff0c;很累的统计&#xff0c;这个是我在项目中发现没办法统计&#xff0c;网上的教程很多&#xff0c;都不成功&…

构建信息蓝图:概念模型与E-R图的技术解析

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…

C# 中 Interpreter 用于解释执行代码的工具

在 C# 中&#xff0c;Interpreter 是一个用于解释执行代码的工具&#xff0c;它提供了一种在运行时动态解释和执行 C# 代码的方式。Interpreter 类位于 Microsoft.CodeAnalysis.CSharp.Scripting 命名空间中&#xff0c;它允许你通过编写代码字符串来执行 C# 代码。 下面是一些…

毫秒生成的时间戳如何转化成东八区具体时间

假设现在有一个时间是1709101071419L 后端代码实现 Java代码&#xff08;东八区时间&#xff09; 在Java代码中&#xff0c;我们将时区从UTC调整为东八区&#xff08;UTC8&#xff09;&#xff1a; import java.time.Instant; import java.time.ZoneId; import java.time.Z…

pytest 教程

1. 安装pytest 目前我使用的python版本是3.10.8 pip install pytest命令会安装下面的包&#xff1a; exceptiongroup-1.2.0-py3-none-any.whl iniconfig-2.0.0-py3-none-any.whl packaging-23.2-py3-none-any.whl pluggy-1.4.0-py3-none-any.whl pytest-8.0.2-py3-none-any.…

CSS3新特性

简介 继CSS2之后&#xff0c;CSS3增加了很多新的特性&#xff0c;虽然W3C仍在规范中&#xff0c;但是很多新的CSS3属性已经在很多现代浏览器中得到了支持。 CSS3边框 在CSS3中&#xff0c;可以创建圆角边框&#xff0c;添加边框阴影&#xff0c;设置边框图片&#xff0c;利用…

页面锚点使用

以下代码直接复制使用 <template><div style"height: 100%;"><div style"display: flex;height: 100%;"><div style"width: 200px;border: 1px solid pink;"><div v-for"(item, index) in titleList" :ke…

NVMe管理命令为何不用SGL?-1

上周末在公众号后台收到粉丝留言&#xff0c;主要是关于SGL的交流&#xff1a;“SGL为啥不能用于nvme admin cmd”&#xff1f; 回答这个问题前&#xff0c;首先&#xff0c;我们先回顾下NVME PRP和SGL的基本原理以及应用场景。 在Host与Controller之间有数据交互时&#xff0…

软件测试零基础新手入门必看

软件测试&#xff1a;使用技术手段验证软件是否满足使用需求 目的&#xff1a;减少缺陷&#xff0c;保证质量 一、测试主流技能&#xff1a; 1.功能测试 测试主要验证程序的功能是否满足需求 2.自动化测试 使用工具或代码代替手工&#xff0c;对项目进行测试 3.接口测试 …

小迪安全32WEB 攻防-通用漏洞文件上传二次渲染.htaccess变异免杀

#知识点&#xff1a; 1、文件上传-二次渲染 2、文件上传-简单免杀变异 3、文件上传-.htaccess 妙用 4、文件上传-PHP 语言特性 #详细点&#xff1a; 1、检测层面&#xff1a;前端&#xff0c;后端等 2、检测内容&#xff1a;文件头&#xff0c;完整性&#xff0c…

常用SQL查询方法与实例

目录 SELECT查询 INSERT查询 UPDATE查询 DELETE查询 JOIN查询 GROUP BY查询 HAVING查询 窗口函数 公共表表达式&#xff08;CTEs&#xff09; 递归查询 透视表 分析函数 解透视 条件聚合 日期函数 合并语句 情况语句 常用SQL查询方法有以下几种&#xff1a; S…

OWASP Top 10 网络安全10大漏洞——A02:A02:2021-加密机制失效

10大Web应用程序安全风险 2021年top10中有三个新类别、四个类别的命名和范围变化&#xff0c;以及一些合并。 A02&#xff1a;A02:2021-加密机制失效 上升一个位置&#xff0c;当前top2&#xff0c;以前称为敏感数据泄露&#xff0c;是一种状况而不是根本原因。更新后的类别…