Unity中使用HttpListener创建本地Http web服务器教程与完整代码

这篇具有很好参考价值的文章主要介绍了Unity中使用HttpListener创建本地Http web服务器教程与完整代码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

下方有完整代码和使用方法,急用的请直接拉到最下方

本文可以实现不开新进程在Unity中创建http服务器。
监听自定义ip获取指定目录下的网页或其他资源。如果网页内有其他资源链接也可以正常访问。
可以配合Unity网页浏览器组件使用解决资源打包问题

在Unity中搭建简易http服务主要分为三步

  1. 监听访问请求
  2. 解析请求
  3. 响应请求

1 监听访问请求

监听服务使用的是System.Net库中的HttpListener组件,并使用其Start()方法对相关端口的访问进行监听

using System;
using System.Net;
public class HttpServer : MonoBehaviour
{
    // 服务器对象
    private  HttpListener listener;
    // 要监听的目标地址
    private string localIp = "http://localhost:8081/";
    // 本地web资源地址
    private string localFilePath = "C:\\Users\\Desktop\\html";
}

一般执行监听有三种方式:
第一种就是用whilet(true)循环监听, 这种方式会阻塞当前线程。
第二种是调用threadingpool线程池开一个线程监听请求,是比较常用的方式
第三种是使用异步监听。本文使用的是第三种

listener.BeginGetContext(Response, null);

listener.BeginGetContext会开启异步监听,监听到访问会回调我们自定义的Response方法并传入请求信息,我们对访问请求的数据解析和响应都要在这个方法中完成,并且要在其中再次调用listener.BeginGetContext方法来保持持续监听

    void Start()
    {
        listener = new HttpListener();
        // 定义url
        listener.Prefixes.Add(localIp);
        listener.Start();
        // 使用异步监听Web请求,当客户端的网络请求到来时会自动执行委托
        listener.BeginGetContext(Response, null);
        // 提示信息
        Debug.Log($"服务已启动 {DateTime.Now.ToString()},访问地址:{localIp}");
    }
    private void Response(IAsyncResult ar)
	{
    	// 再次开启异步监听
    	listener.BeginGetContext(Response, null);
    }

2 解析请求

解析请求的目的是根据访问地址来定位文件资源的目录和区分文件不同类型的处理办法。
比如访问的地址是www.baidu.com/folder/index.html,我们首先要得到/folder/index.html这个文件相对地址来定位这个文件在本地磁盘上的路径,然后得到html这个文件的扩展名,来对html文件的处理方式做专门的说明

var context = listener.EndGetContext(ar)用来获取传入的请求数据
var request = context.Request; 用来获取请求信息

private void Response(IAsyncResult ar)
{
    // 再次开启异步监听
    listener.BeginGetContext(Response, null);
    Debug.Log($"{DateTime.Now.ToString()}接到新的请求");

    // 获取context对象
    var context = listener.EndGetContext(ar);
    // 获取请求体
    var request = context.Request;
    
    // 配置响应结构
    try
    {
        // 获取网址中指定的文件名,比如www.baidu.com/show.html, 这里会得到show.如果为空就默认为index.html
        string filename = context.Request.Url.AbsolutePath.Trim('/');
        if (filename == "")
        {
            filename = "index.html";
        }

        // 获取文件扩展名,比如file.jpg,这里拿到的就是jpg
        string[] ext_list = filename.Split('.');
        string ext = ext_list.Length > 1? ext_list[ext_list.Length - 1]:"";
    }
}

3 响应请求

响应请求要做的是,组织好要提供给访问者的资源,然后指明该资源在浏览器中应该怎样呈现
在这一部分中,

我们首先根据解析出来的文件相对路径与设置好的本地资源目录来获得目标资源的绝对路径:string absPath = Path.Combine(localFilePath, filename);

然后为html扩展名的文件设置响应头信息,让他以网页的形式在浏览器中正常展示:switch (ext){ case “html”: context.Response.ContentType = “text/html”;

接着将文件数据转为数据 msg = File.ReadAllBytes(absPath);context.Response.ContentLength64 = msg.Length;

最后将数据发给客户端 using (Stream s = context.Response.OutputStream) { s.Write(msg, 0, msg.Length); }

 private void Response(IAsyncResult ar)
 {
         // 获取网址中指定的文件名,比如www.baidu.com/show.html, 这里会得到show.如果为空就默认为index.html
         string filename = context.Request.Url.AbsolutePath.Trim('/');
         if (filename == "")
         {
             filename = "index.html";
         }

         // 获取文件扩展名,比如file.jpg,这里拿到的就是jpg
         string[] ext_list = filename.Split('.');
         string ext = ext_list.Length > 1? ext_list[ext_list.Length - 1]:"";
         // 根据结合本地资源目录和网址中的文件地址,得到要访问的文件的绝对路径
         string absPath = Path.Combine(localFilePath, filename);
         
         // 设置响应状态,就是网页响应码。ok == 200
         context.Response.StatusCode = (int)HttpStatusCode.OK;
         string expires = DateTime.Now.AddYears(10).ToString("r");

         // 根据文件扩展名配置不同的网页响应头
         switch (ext)
         {
             case "html":
             case "htm":
                 context.Response.ContentType = "text/html";
                 break;
             case "js":
                 context.Response.ContentType = "application/x-javascript";
                 context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                 context.Response.AddHeader("expires", expires);
                 break;
             case "css":
                 context.Response.ContentType = "text/css";
                 context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                 context.Response.AddHeader("expires", expires);
                 break;
             case "jpg":
             case "jpeg":
             case "jpe":
                 context.Response.ContentType = "image/jpeg";
                 context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                 context.Response.AddHeader("expires", expires);
                 break;
             case "png":
                 context.Response.ContentType = "image/png";
                 context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                 context.Response.AddHeader("expires", expires);
                 break;
             case "gif":
                 context.Response.ContentType = "image/gif";
                 context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                 context.Response.AddHeader("expires", expires);
                 break;
             case "ico":
                 context.Response.ContentType = "application/x-ico";
                 context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                 context.Response.AddHeader("expires", expires);
                 break;
             case "txt":
                 context.Response.ContentType = "text/plain";
                 break;
             case "do":
                 context.Response.AddHeader("Access-Control-Allow-Origin", "*");
                 context.Response.ContentType = "text/plain;charset=utf-8";
                 break;
             default:
                 context.Response.ContentType = "";
                 context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                 context.Response.AddHeader("expires", expires);
                 break;
         }

         // 组织数据流
         byte[] msg = new byte[0];
         if (msg.Length == 0)
         {
             // 如果目标文件不存在就显示错误页面
             if (!File.Exists(absPath))
             {
                 context.Response.ContentType = "text/html";
                 context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                 if (File.Exists(localFilePath + "error.html"))
                 {
                     msg = File.ReadAllBytes(localFilePath + "error.html");
                 }
                 else
                 {
                     msg = Encoding.Default.GetBytes("404");
                 }
             }
             // 如果存在就将文件转为byte流
             else
             {
                 msg = File.ReadAllBytes(absPath);
             }
         }
         // 返回字节流
         context.Response.ContentLength64 = msg.Length;
         using (Stream s = context.Response.OutputStream)
         {
             s.Write(msg, 0, msg.Length);
         }

         msg = new byte[0];
         GC.Collect();
     }
     catch (Exception ex)
     {
     }
 }

最后清空数据即可: msg = new byte[0]; GC.Collect();

完整代码及使用方式

使用方式:

  1. 在Unity中创建cs脚本其名为HttpServer.cs,将下方代码copy进去保存
  2. 修改成想要监控的地址:private string localIp = “http://localhost:8081/”;
  3. 修改成允许被访问的本地资源目录:private string localFilePath = “C:\Users\Desktop\html”;
  4. 在Unity场景中创建GameObject,然后为该对象添加HttpServer组件
  5. 运行Unity
  6. 打开浏览器访问http://localhost:8081/

完整代码:文章来源地址https://www.toymoban.com/news/detail-781609.html

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Text;
using System.IO;

public class HttpServer : MonoBehaviour
{
    // 服务器对象
    private  HttpListener listener;
    private string localIp = "http://localhost:8081/";
    // 本地web资源地址
    private string localFilePath = "C:\\Users\\Desktop\\html";

    void Start()
    {
        listener = new HttpListener();
        // 定义url
        listener.Prefixes.Add(localIp);
        listener.Start();
        // 使用异步监听Web请求,当客户端的网络请求到来时会自动执行委托
        listener.BeginGetContext(Response, null);
        // 提示信息
        Debug.Log($"服务已启动 {DateTime.Now.ToString()},访问地址:{localIp}");
    }

    /// <summary>
    ///  处理收到的访问请求
    /// </summary>
    /// <param name="ar">包含请求体的参数</param>
    private void Response(IAsyncResult ar)
    {
        // 再次开启异步监听
        listener.BeginGetContext(Response, null);
        Debug.Log($"{DateTime.Now.ToString()}接到新的请求");

        // 获取context对象
        var context = listener.EndGetContext(ar);
        // 获取请求体
        var request = context.Request;
        // 获取响应结构
        var response = context.Response;

        try
        {
            // 获取网址中指定的文件名,比如www.baidu.com/show.html, 这里会得到show.如果为空就默认为index.html
            string filename = context.Request.Url.AbsolutePath.Trim('/');
            if (filename == "")
            {
                filename = "index.html";
            }

            // 获取文件扩展名,比如file.jpg,这里拿到的就是jpg
            string[] ext_list = filename.Split('.');
            string ext = ext_list.Length > 1? ext_list[ext_list.Length - 1]:"";
            // 根据结合本地资源目录和网址中的文件地址,得到要访问的文件的绝对路径
            string absPath = Path.Combine(localFilePath, filename);
            
            // 设置响应状态,就是网页响应码。ok == 200
            context.Response.StatusCode = (int)HttpStatusCode.OK;
            string expires = DateTime.Now.AddYears(10).ToString("r");

            // 根据文件扩展名配置不同的网页响应头
            switch (ext)
            {
                case "html":
                case "htm":
                    context.Response.ContentType = "text/html";
                    break;
                case "js":
                    context.Response.ContentType = "application/x-javascript";
                    context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                    context.Response.AddHeader("expires", expires);
                    break;
                case "css":
                    context.Response.ContentType = "text/css";
                    context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                    context.Response.AddHeader("expires", expires);
                    break;
                case "jpg":
                case "jpeg":
                case "jpe":
                    context.Response.ContentType = "image/jpeg";
                    context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                    context.Response.AddHeader("expires", expires);
                    break;
                case "png":
                    context.Response.ContentType = "image/png";
                    context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                    context.Response.AddHeader("expires", expires);
                    break;
                case "gif":
                    context.Response.ContentType = "image/gif";
                    context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                    context.Response.AddHeader("expires", expires);
                    break;
                case "ico":
                    context.Response.ContentType = "application/x-ico";
                    context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                    context.Response.AddHeader("expires", expires);
                    break;
                case "txt":
                    context.Response.ContentType = "text/plain";
                    break;
                case "do":
                    context.Response.AddHeader("Access-Control-Allow-Origin", "*");
                    context.Response.ContentType = "text/plain;charset=utf-8";
                    break;
                default:
                    context.Response.ContentType = "";
                    context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                    context.Response.AddHeader("expires", expires);
                    break;
            }

            // 组织数据流
            byte[] msg = new byte[0];
            if (msg.Length == 0)
            {
                // 如果目标文件不存在就显示错误页面
                if (!File.Exists(absPath))
                {
                    context.Response.ContentType = "text/html";
                    context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    if (File.Exists(localFilePath + "error.html"))
                    {
                        msg = File.ReadAllBytes(localFilePath + "error.html");
                    }
                    else
                    {
                        msg = Encoding.Default.GetBytes("404");
                    }
                }
                // 如果存在就将文件转为byte流
                else
                {
                    msg = File.ReadAllBytes(absPath);
                }
            }
            // 返回字节流
            context.Response.ContentLength64 = msg.Length;
            using (Stream s = context.Response.OutputStream)
            {
                s.Write(msg, 0, msg.Length);
            }

            msg = new byte[0];
            GC.Collect();
        }
        catch (Exception ex)
        {
        }

        // 跨域等设置
        // context.Response.AppendHeader("Access-Control-Allow-Headers", "ID,PW");
        // context.Response.AppendHeader("Access-Control-Allow-Method", "post");
        // context.Response.AppendHeader("Access-Control-Allow-Origin", "*"); // 允许跨域请求
        // context.Response.ContentType = "text/plain;charset=UTF-8"; // 响应类型为UTF-8纯文本格式
        // context.Response.AddHeader("Content-type", "text/plain"); // 添加响应头
        // context.Response.ContentEncoding = Encoding.UTF8;
    }

    private void OnDestroy()
    {
        // httpobj.EndGetContext(null);
    }
}

到了这里,关于Unity中使用HttpListener创建本地Http web服务器教程与完整代码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity导出WebGL工程,并部署本地web服务器

    在Build Settings-PlayerSettings-Other Settings-Rendering 将Color Space 设置为Gamma 将Lightmap Encoding 设置为NormalQuality 在Build Settings-PlayerSettings-Publishing Settings 勾选Decompression Fallback 完成配置修改之后,可以直接在Build界面选择Build And Run,构建结束后会由Unity自动部署,可以正常打开网页。 如果

    2023年04月19日
    浏览(53)
  • 本地开发 npm 好用的http server、好用的web server、静态服务器

    有时需要快速启动一个web 服务器(http服务器)来伺服静态网页,安装nginx又太繁琐,那么可以考虑使用npm serve、http-server、webpack-dev-server。 npm 的serve可以提供给http server功能, 如果你想提供 静态站点 、 单页面应用 或者 静态文件 甚至罗列文件夹的内容服务,那么npm serve 是

    2024年02月14日
    浏览(39)
  • http-server使用,启动本地服务器 & 使用serve包本地启动

    http-server使用,启动本地服务器 使用serve包本地启动 直接打开html文件,跨域不渲染图片 1、简介 官网:https://github.com/http-party/http-server http-server是一个简单的零配置命令行 http服务器 。 它足够强大,足以用于生产用途,但它既简单又易于破解,可用于测试,本地开发和学习。

    2024年02月02日
    浏览(56)
  • 使用 Node 创建 Web 服务器

    Node.js 提供了 http 模块,http 模块主要用于搭建 HTTP 服务端和客户端,使用 HTTP 服务器或客户端功能必须调用 http 模块,代码如下: 以下是演示一个最基本的 HTTP 服务器架构(使用 8080 端口),创建 server.js 文件,代码如下所示: 接下来我们在该目录下创建一个 index.html 文件,代

    2024年01月23日
    浏览(53)
  • 使用Docker在Linux服务器本地部署PaddleSpeech Web服务

    1. 从官方Docker Hub拉取环境 2. 启动容器并分派端口 3. 自然语言处理工具库NLTK安装 方法一:使用 nltk 自带的 download() 下载,由于国内网络问题,大概率失败。 方法二:从下载文件手动安装包。 链接:https://pan.baidu.com/s/1nQveCEAucFSNbuOAsrs6yw?pwd=yydh 提取码:yydh 从百度网盘下载nlt

    2024年01月20日
    浏览(51)
  • WPF项目创建HTTP WEB服务,不使用IIS业务 WPF桌面程序WebApi WPF 集成WebApi C# 创建HTTP Web API服务

    在C# WPF应用程序中直接创建HTTP服务或WebAPI服务有以下优点: 自托管服务: 简化部署:无需依赖外部服务器或IIS(Internet Information Services),可以直接在应用程序内部启动和运行Web服务。 集成紧密:与WPF应用程序的其他组件和逻辑可以更紧密地集成,因为它们都在同一个进程

    2024年02月02日
    浏览(62)
  • 使用IDEA部署Web项目到本地的Tomcat服务器

    1.1 Tomcat下载与安装启动 下载地址:http://tomcat.apache.org/ (左侧Download选择下载版本) 1.1.1 安装: 1、下载好了解压到一个没有特殊符号的目录中(一般纯英文即可) 2、进入到解压的目录下找到binstartup.bat双击启动即可 tomcat需要配置JAVA_HOME环境变量,不要把bin目录也配置到JAVA

    2024年02月13日
    浏览(54)
  • IntelliJ IDEA创建Web项目并使用Web服务器----Tomcat

    以下是本篇文章正文内容,下面案例可供参考(提示:本篇文章属于原创,请转发或者引用时注明出处。),大家记得支持一下!!!! 每日清醒: ✌✌✌♘慢慢来,谁还没有一个努力的过程。🏆 一定要注意:别忘了设置好之后点击应用!!!!!!!!! maven项目的重点

    2024年02月10日
    浏览(70)
  • linux高并发web服务器开发(web服务器)18_函数解析http请求, 正则表达式,sscanf使用,http中数据特殊字符编码解码

    pdf详情版 编写函数解析http请求 ○ GET /hello.html HTTP/1.1rn ○ 将上述字符串分为三部分解析出来 编写函数根据文件后缀,返回对应的文件类型 sscanf - 读取格式化的字符串中的数据 ○ 使用正则表达式拆分 ○ [^ ]的用法 通过浏览器请求目录数据 ○ 读指定目录内容  opendir 

    2024年02月16日
    浏览(59)
  • 使用 cpolar 内网穿透将本地 web 网站发布上线(无需服务器)

    当我们以本地电脑做服务器搭建web网站时,如何将它发布到互联网上,实现公网用户都可以访问内网的web网站就变得很重要。 这里我们以macOS系统自带的Apache为例,在本地启用Apache服务器,并通过cpolar内网穿透将其暴露至公网,实现在外公网环境下访问本地web服务,无需购买

    2024年01月23日
    浏览(71)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包