Ubuntu本地快速搭建web小游戏网站,并使用内网穿透将其发布到公网上

news2024/12/23 3:15:02

文章目录

  • 前言
  • 1. 本地环境服务搭建
  • 2. 局域网测试访问
  • 3. 内网穿透
    • 3.1 ubuntu本地安装cpolar内网穿透
    • 3.2 创建隧道
    • 3.3 测试公网访问
  • 4. 配置固定二级子域名
    • 4.1 保留一个二级子域名
    • 4.2 配置二级子域名
    • 4.3 测试访问公网固定二级子域名

前言

网:我们通常说的是互联网;站:可以理解成在互联网上的一个房子。把互联网看做一个城市,城市里面的每一个房子就是一个站点,房子里面放着你的资源,那如果有人想要访问你房子里面的东西怎么办?

在现实生活中,去别人家首先要知道别人的地址,某某区某某街道,几号,在互联网中也有地址的概念,就是ip。通过ip我们就能找到在互联网上面的站点,端口可以看做是这个房子的入口,不同的入口所看到的东西也就不一样,如从大门(80端口)进是客厅,从窗户(8080端口)进是书房。

接下来我们将通过简单几步来在ubuntu搭建一个web站点 html小游戏,并使用cpolar内网穿透将其发布到公网上,使得公网用户也可以正常访问到本地web站点的小游戏。

1. 本地环境服务搭建

apach2是一个服务,也可以看做一个容器,也就是上面说的房子,运行在ubuntu里,这个服务可以帮助我们把我们自己的网站页面通过相应的端口让除本机以外的其他电脑访问。

下载apach2

sudo apt install apache2 php -y

20230215171101

下载好后启动apache2

sudo service apache2 restart

然后打开Ubuntu 浏览器,输入:http://localhost 即可看到我们apache 默认的页面,此时说明本地站点已经搭建好了。

·20230215171102

进入Apache默认服务器主目录路径,这个目录放的是想要让别人看到的资源,如一张图片,一个html页面等

cd /var/www/html

进入后删掉index.html这个文件,由于apache默认页面并不是我们自己想要的页面,我们想要换成自己喜欢的页面,所以需要删掉.执行以下命令:

sudo rm -rf index.html

为了达到测试效果,我们设置一个html页面小游戏,创建名称为game.html的页面

sudo vim game.html

i键 进入编辑模式,复制以下html代码进去(复制全部)

<!DOCTYPE html>
<html>
    <head><h4>Take it Easy!Please playing Game</h4></head>
    <body>
		<div></div>
        <!-- 4个board -->
        <div id="board1" style="position: absolute; width:80px; height:10px; left:420px; 
        top:555px; background-color: cadetblue;"></div>
        <div id="board2" style="position: absolute; width:80px; height:10px; left:520px; 
        top:555px; background-color: cadetblue;"></div>
        <div id="board3" style="position: absolute; width:80px; height:10px; left:620px; 
        top:555px; background-color: cadetblue;"></div>
        <div id="board4" style="position: absolute; width:80px; height:10px; left:720px; 
        top:555px; background-color: cadetblue;"></div>
        <!-- 小球 -->
        <div id="ball" class="circle" style="width:20px; 
        height:20px; background-color:crimson; border-radius: 50%; position:absolute; 
        left:600px; top:100px"></div>
        <!-- 框 -->
        <div id="box" style="border: 5px solid #555555; width:400px; height:550px; display=hide"></div>
        <!-- 分数 过的board越多,分数越高 -->
        <div id="score" style="width:200px; height:10px; position:absolute; left:900px; 
            font-family:'隶书'; font-size: 30px;">score: 0</div>
        <!-- 游戏结束 -->
        <div id="gg" style="width:200px; height:10px; position:absolute; left:550px; top:200px;
        font-family:'隶书'; font-size: 30px; display: none;">Game Over</div>
        <script>
            // 设置box的样式
            var box = document.getElementById("box");
            box.style.position = "absolute";
            box.style.left = "400px";
            // 设置board的样式
            var board1 = document.getElementById("board1");
            var board2 = document.getElementById("board2");
            var board3 = document.getElementById("board3");
            var board4 = document.getElementById("board4");
            // 声音
            var shengyin = new Audio();
            shengyin.src = "声音2.mp3";
            shengyinFlag = 0; // 用来表示小球在第几块board上
            // 键盘事件函数
            var ball = document.getElementById("ball");
            document.onkeydown = f;
            function f(e){
                var e = e || window.event;
                switch(e.keyCode){
                    case 37:
                        // 按下左键,小球左移,但不要超过左边框
                        if(ball.offsetLeft>=box.offsetLeft + 10)
                            ball.style.left = ball.offsetLeft - 8 + "px";
                        break;
                    case 39:
                        // 按下右键,小球右移,但不要超过由边框
                        if(ball.offsetLeft<=box.offsetLeft+box.offsetWidth-ball.offsetWidth-10)
                            ball.style.left = ball.offsetLeft + 8 + "px";
                        break;
                    case 32:
                        
                }
            }
            // 定义一个分数变量
            var fenshu = 0;
            // 定义一个函数,移动给定的一个board
            function moveBoard(board)
            {
                var t1 = board.offsetTop;
                if(t1<=0)
                {
                    // 如果board移到最上面了,就随机换个水平位置,再移到最下面
                    t2 = Math.floor(Math.random() * (720- 420) + 420);
                    board.style.left = t2 + "px";
                    board.style.top = "555px";
                    fenshu += 1; //分数增加1
                    document.getElementById("score").innerHTML = "score " + fenshu;
                }
                    // 
                else
                    board.style.top = board.offsetTop - 1 + "px";
            }
            // 定义小球的速度变量
            var startSpeed = 1;
            var ballSpeed =startSpeed;
            // step函数是游戏界面的单位变化函数
            function step()
            {
                // board直接上下隔得太近,就逐个移动,否则,同时移动
                var t1 = Math.abs(board1.offsetTop - board2.offsetTop);
                var t2 = Math.abs(board2.offsetTop - board3.offsetTop);
                var t3 = Math.abs(board3.offsetTop - board4.offsetTop);
                // 定义一个board之间的间隔距离
                var t4 = 140;
                if(t1<t4)
                {
                    moveBoard(board1);
                }
                else if(t2<t4)
                {
                    moveBoard(board1);
                    moveBoard(board2);
                }
                else if(t3<t4)
                {
                    moveBoard(board1);
                    moveBoard(board2);
                    moveBoard(board3);
                }
                else
                {
                    moveBoard(board1);
                    moveBoard(board2);
                    moveBoard(board3);
                    moveBoard(board4);
                }
                // 定义小球的垂直移动规则,1、向下匀加速运动,2、如果碰到board就被board持续抬上去,
                // 直到按左右键离开了该board

                // 如果小球的纵坐标等于某个board的纵坐标,就被抬起
                var t5 = Math.abs(ball.offsetTop - board1.offsetTop);
                var t6 = Math.abs(ball.offsetTop - board2.offsetTop);
                var t7 = Math.abs(ball.offsetTop - board3.offsetTop);
                var t8 = Math.abs(ball.offsetTop - board4.offsetTop);
                if(t5<=ball.offsetHeight && t5>0 && ball.offsetLeft>=board1.offsetLeft-ball.offsetWidth && ball.offsetLeft<=board1.offsetLeft+board1.offsetWidth)
                {
                    ball.style.top = board1.offsetTop - ball.offsetHeight + "px";
                    ballSpeed = startSpeed;
                    if(shengyinFlag != 1)
                    {
                        shengyin.play();
                        shengyinFlag = 1;
                    }
                }
                else if(t6<=ball.offsetHeight && t6>0 && ball.offsetLeft>=board2.offsetLeft-ball.offsetWidth && ball.offsetLeft<=board2.offsetLeft+board2.offsetWidth)
                {
                    ball.style.top = board2.offsetTop - ball.offsetHeight + "px";
                    ballSpeed = startSpeed;
                    if(shengyinFlag != 2)
                    {
                        shengyin.play();
                        shengyinFlag = 2;
                    }
                }
                else if(t7<=ball.offsetHeight && t7>0 && ball.offsetLeft>=board3.offsetLeft-ball.offsetWidth && ball.offsetLeft<=board3.offsetLeft+board3.offsetWidth)
                {
                    ball.style.top = board3.offsetTop - ball.offsetHeight + "px";
                    ballSpeed = startSpeed;
                    if(shengyinFlag != 3)
                    {
                        shengyin.play();
                        shengyinFlag = 3;
                    }
                }
                else if(t8<=ball.offsetHeight && t8>0 && ball.offsetLeft>=board4.offsetLeft-ball.offsetWidth && ball.offsetLeft<=board4.offsetLeft+board4.offsetWidth)
                {
                    ball.style.top = board4.offsetTop - ball.offsetHeight + "px";
                    ballSpeed = startSpeed;
                    if(shengyinFlag != 4)
                    {   
                        shengyin.play();
                        shengyinFlag = 4;
                    }
                }
                else
                {
                    ballSpeed = ballSpeed + 0.01; // 数字相当于加速度
                    ball.style.top = ball.offsetTop + ballSpeed + "px";
                }
                // ballSpeed = ballSpeed + 0.01; // 数字相当于加速度
                // ball.style.top = ball.offsetTop + ballSpeed + "px";
                
                // 如果小球跑出来box,就结束游戏
                if(ball.offsetTop==0 || ball.offsetTop>=box.offsetTop+box.offsetHeight)
                {
                    clearInterval(gameover);
                    ball.style.display = 'none';
                    board1.style.display = 'none';
                    board2.style.display = 'none';
                    board3.style.display = 'none';
                    board4.style.display = 'none';
                    var gg = document.getElementById("gg"); //显示游戏结束
                    gg.style.display = 'block';
                }
            }

            var gameover = setInterval("step();", 8);
        </script>
    </body>
</html>

20230215171103

复制完后按Esc键退出编辑,接着输入冒号:wq保存退出即可

2. 局域网测试访问

接着浏览器输入http://localhost/game.html,即可看到html页面的小游戏站点,由于部署的是静态站点,不需要重启服务。

20230215171104

3. 内网穿透

由于这个站点目前只能在本地被访问到,为了使所有人都可以访问,我们需要将这个本地基础站点发布到公网。这里我们可以通过cpolar内网穿透工具来实现,它支持 http/https/tcp协议,无需公网IP ,也不用设置路由器,可以很容易将本地站点发布到公网供所有人访问。

3.1 ubuntu本地安装cpolar内网穿透

cpolar官网:https://www.cpolar.com/

  • cpolar支持一键自动安装脚本
curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bash
  • token认证

登录cpolar官网后台,点击左侧的验证,查看自己的认证token,之后将token贴在命令行里:

cpolar authtoken xxxxxxx

20230327161256

  • 简单穿透测试,穿透成功有正常生成公网地址,按ctrl+c退出
cpolar http 8080
  • 向系统添加服务,将cpolar配置为开机自启
sudo systemctl enable cpolar
  • 启动cpolar服务
sudo systemctl start cpolar
  • 查看服务状态,正常显示为active表示启动成功,为正常在线状态
sudo systemctl status cpolar

3.2 创建隧道

cpolar安装成功之后,在浏览器上访问本地9200端口,登录cpolar web UI管理界面。

20230215171953

点击左侧仪表盘的隧道管理——创建隧道:

  • 隧道名称:可自定义,注意不要重复
  • 协议:http
  • 本地地址:80
  • 端口类型:随机域名
  • 地区:China vip

点击创建

20230215171105

隧道创建成功后,点击左侧的状态——在线隧道列表,可以看到刚刚创建的隧道已经有生成了相应的公网地址,将其复制下来,接下来测试访问一下。

20230215171106

3.3 测试公网访问

打开浏览器访问刚刚所复制的公网地址,注意,后面要加上路径/game.html,出现游戏界面即成功。

游戏控制使用:键盘上下左右键

20230215171107

4. 配置固定二级子域名

由于以上所创建的隧道选择的是随机域名,所生成的公网地址会在24小时内随机变化,对于需要长期访问的用户来讲较为不方便。不过我们可以为其配置一个固定的二级子域名来进行访问,改地址不会随机变化。

注意:配置固定二级子域名功能需要升级至基础版套餐或以上才支持。

4.1 保留一个二级子域名

登录cpolar官网后台,点击左侧的预留,找到保留二级子域名:

  • 地区:选择China VIP
  • 二级域名:可自定义填写
  • 描述:即备注,可自定义填写

点击保留

20230215171108

提示子域名保留成功,复制所保留的二级子域名

20230215171109

4.2 配置二级子域名

访问本地9200端口登录cpolar web UI管理界面,点击左侧仪表盘的隧道管理——隧道列表,找到所要配置的隧道,点击右侧的编辑

20230215171110

修改隧道信息,将保留成功的二级子域名配置到隧道中

  • 域名类型:选择二级子域名
  • Sub Domain:填写保留成功的二级子域名,本例为test01

点击更新

20230215171111

提示更新隧道成功,点击左侧仪表盘的状态——在线隧道列表,可以看到公网地址已经更新为保留成功的二级子域名,将其复制下来。

20230215171112

4.3 测试访问公网固定二级子域名

我们使用任意浏览器,输入刚刚配置成功的公网固定二级子域名+/game.html即可看到我们创建的站点小游戏

20230215171113

转载自cpolar极点云的文章:在Ubuntu搭建Web站点,并将其发布到公网访问

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot中乐观锁的实现 (精简demo)

使用场景: 当要更新一条数据时&#xff0c;希望这条数据没有被别人更新&#xff0c;也就是说实现线程安全的数据更新 1. 数据库新增version字段, int类型, 默认值为0 2. 引入依赖 <!--mybatis拦截器--> <dependency><groupId>com.baomidou</groupId>&…

Nginx使用keepalived配置VIP

VIP常用于负载均衡的高可用&#xff0c;使用VIP可以给多个主机绑定一个IP&#xff0c;这样&#xff0c;当某个负载应用挂了之后&#xff0c;可以自动切到另一个负载。 我这里是在k8s环境中做的测试&#xff0c;集群中有6个节点&#xff0c;我给140和141两个节点配置VIP。 1. 安…

【leetcode 力扣刷题】移除链表元素 多种解法

移除链表元素的多种解法 203. 移除链表元素解法①&#xff1a;头节点单独判断解法②&#xff1a;虚拟头节点解法③&#xff1a;递归 203. 移除链表元素 题目链接&#xff1a;203.移除链表元素 题目内容&#xff1a; 理解题意&#xff1a;就是单纯的删除链表中所有值等于给定的…

Java【HTTP】什么是 Cookie 和 Session? 如何理解这两种机制的区别和作用?

文章目录 前言一、Cookie1, 什么是 Cookie2, Cookie 从哪里来3, Cookie 到哪里去4, Cookie 有什么用 二、Session1, 什么是 Session2, 理解 Session 三、Cookie 和 Session 的区别总结 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: &#x1f4d5; …

并查集 size 的优化(并查集 size 的优化)

目录 并查集 size 的优化 Java 实例代码 UnionFind3.java 文件代码&#xff1a; 并查集 size 的优化 按照上一小节的思路&#xff0c;我们把如下图所示的并查集&#xff0c;进行 union(4,9) 操作。 合并操作后的结构为&#xff1a; 可以发现&#xff0c;这个结构的树的层相对…

juc概述和Lock接口

目录 一、什么是JUC 1、JUC概述 2、进程与线程 3、线程的状态 4、wait/sleep 的区别 5、并发与并行 6、管程 7、用户线程和守护线程 二、Lock接口 1、Synchronized 使用synchronized实现售票案例 使用synchronized实现增减变量操作 2、什么是 Lock 买票例子使用lo…

如何选择 DCDC 降压型开关电源的电感

选择合适的电感是开关电源电路设计的关键之一。本文将帮助您理解电感值和电路性能之间的关系。 降压转换器&#xff08;buck converter&#xff09;&#xff0c;也称为降压转换器(step-down converter)&#xff0c;是一种开关模式稳压器&#xff08;voltage regulator&#xf…

Mac常见恶意软件再现,办公应用程序潜藏风险如何防范?

Mac电脑正受到臭名昭著的XLoader恶意软件的新变种的攻击&#xff0c;该恶意软件已被重写为在最好的MacBook上本地运行。 虽然XLoader至少从2015年开始出现&#xff0c;但在2021年发现macOS变体之前&#xff0c;它主要用于针对Windows PC。然而&#xff0c;该版本是作为Java程序…

win10系统rust串口通信实现

一、用cargo创建新工程 命令&#xff1a;cargo new comport use std::env; use std::{thread, time}; use serialport::{DataBits, StopBits, Parity, FlowControl}; use std::io::{self, Read, Write}; use std::time::Duration;fn main() -> io::Result<()> {let m…

CSS中的display属性有哪些值?它们的作用?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ CSS display 属性的不同取值和作用1. block2. inline3. inline-block4. none5. flex6. grid7. table、table-row、table-cell8. list-item9. inline-table、table-caption、table-column 等 ⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#x…

Pika Labs - 用AI工具生成短视频大片

今天我要跟大家分享如何用AI工具1分钟内生成一个短视频大片&#xff0c;效果完全不输影视大V。 只需要用一句话就可以生成视频&#xff0c;或者用一张图就能生成视频&#xff0c;这就是最新推出的AI工具Pika Labs&#xff01;被网友誉为“全球最优秀的文本生成视频AI”。 目前…

SharedPreferences详解及其ANR解决方案

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、使用四、原理五、存在的问题六、优…

Android动态添加和删除控件/布局

一、引言 最近在研究RecyclerView二级列表的使用方法&#xff0c;需要实现的效果如下。 然后查了一些博客&#xff0c;觉得实现方式太过复杂&#xff0c;而且这种方式也不是特别受推荐&#xff0c;所以请教了别人&#xff0c;得到了一种感觉还不错的实现方式。实现的思路为&…

【LeetCode-经典面试150题-day9]

目录 36.有效的数独 54.螺旋矩阵 48.旋转图像 73.矩阵置零 36.有效的数独 题意&#xff1a; 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1…

huggingface datasets离线加载文件的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Sim/circuit10

通过观察可知&#xff0c;在a、b同时为0或1时&#xff0c;state的值改变 state的值可以改变q的输出&#xff0c;1为ab的同或&#xff0c;0为异或 利用assign q进行输出 module top_module (input clk,input a,input b,output q,output state );always(posedge clk)if(a&…

【TypeScript】元组

元组&#xff08;Tuple&#xff09;是 TypeScript 中的一种特殊数据类型&#xff0c;它允许你定义一个固定数量和类型的元素组合。元组可以包含不同类型的数据&#xff0c;每个数据的类型在元组中都是固定的。以下是 TypeScript 中元组的基本用法和特点&#xff1a; // 声明一…

Win系统下安装Linux双系统教程

软件下载 软件&#xff1a;Linux版本&#xff1a;18.0.4语言&#xff1a;简体中文大小&#xff1a;1.82G安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①丨百度网盘&#xff1a;1.ubuntu18.0.4下载链接&#xf…

量子计算对信息安全的影响:探讨量子计算技术对现有加密方法和信息安全基础设施可能带来的颠覆性影响,以及应对策略

第一章&#xff1a;引言 随着科技的迅猛发展&#xff0c;量子计算作为一项颠覆性的技术正逐渐走入我们的视野。量子计算以其强大的计算能力引发了全球科技界的广泛关注。然而&#xff0c;正如硬币的两面&#xff0c;量子计算技术所带来的不仅仅是计算能力的巨大飞跃&#xff0…

公文校对的艺术:如何确保你的正式文件零错误?

公文是政府和企业中最重要的正式文件之一。一个小小的错误&#xff0c;不仅会影响公文的专业性&#xff0c;甚至可能带来法律和经济后果。因此&#xff0c;如何进行精准的公文校对成为了一门必不可少的技能。接下来&#xff0c;我们将分享一些专业的公文校对技巧&#xff0c;并…