本篇是 Http 服务器系列博文的第十篇,对应项目是 LiteHttp,具体可访问 http://dreamyouxi.com/litehttp.html

Unity 引擎中 C# 脚本的运行环境是 Mono 平台,而非微软的 .NET,Unity 引擎本身大部分由 C++ 编写。

在 LiteHttp 项目中,原本已支持 Lua 脚本来书写动态网页。这里引入 C# 脚本,目的是辅助 C++ 端的开发工作。

把 C# 当脚本语言来使用,相比 Lua 优势更多,底层依然基于 C++ 构建。

环境搭建

step1:去 Mono 官网下载 msi 安装包,x64 和 x86 分别对应 64 位和 32 位 exe。

step2:编写 C# 与 C++ 测试代码。

C++ 端示例:

C# 端示例:

C++ 运行结果:

在 LiteHttpSvr 中的初步应用:文件系统

将原本 C++ 端的文件读取与缓存逻辑迁移到 C# 实现。

C++ 端的修改:

C# 端实现:

using System;
using System.Collections.Generic;
using System.IO;

namespace LiteHttpScript
{
    class CppEntry
    {
        static string CallMain(string file)
        {
            try
            {
                //System.Console.WriteLine("[C# Handle]:" + file);
                return FileCache.Handle(file);
            }
            catch (Exception e)
            {
                System.Console.WriteLine("Err:" + e.Message);
                return "";
            }
        }
    }
    public class FileCache
    {
        static FileCacheImpl impl = new FileCacheImpl();
        public static string Handle(string file)
        {
            lock (impl)
            {
                return impl.GetFile(file);
            }
        }
    };

    //sample LRU file cache which limited by memory
    public class FileCacheImpl
    {
        class FileData
        {
            public string key;
            public string data;
            public DateTime lastModifyUTCTime;
        }

        public string GetFile(string file)
        {
            LinkedListNode<FileData> ret = null;

            if (_cache.TryGetValue(file, out ret))
            {
                //has find cache
                _list.Remove(ret);
                _list.AddFirst(ret);
                //check file will update or not

            }
            else
            {
                //missing cache
                try
                {
                    var data = new FileData();
                    var info = new FileInfo(file);
                    data.lastModifyUTCTime = info.LastWriteTimeUtc;
                    data.data = File.ReadAllText(file);
                    data.key = file;

                    ret = new LinkedListNode<FileData>(data);

                    _list.AddFirst(ret);
                    _cache.Add(file, ret);

                    _currentMemoryUseage += data.data.Length;
                }
                catch (Exception e)
                {
                    //file not exist
                    return "";
                }
            }

            while (_list.Count > 1 && _currentMemoryUseage >= MaxMenmoryCacheSize)
            {
                var tail = _list.Last;
                _cache.Remove(tail.Value.Value.key);
                _list.RemoveLast();
                _currentMemoryUseage -= tail.Value.Value.data.Length;
            }
            //GC.Collect();
            return ret.Value.data;
        }


        // private long MaxMenmoryCacheSize { get { return 104857600L; } }//最大缓存大小 100 MB
        private long MaxMenmoryCacheSize { get { return 100L; } }//最大缓存大小 100 MB


        //   private long MaxCacheFileNum { get { return 1024; } }//最大文件缓存数量

        private long _currentMemoryUseage = 0;

        private Dictionary<string, LinkedListNode<FileData>> _cache = new Dictionary<string, LinkedListNode<FileData>>();

        private LinkedList<LinkedListNode<FileData>> _list = new LinkedList<LinkedListNode<FileData>>();
    };

}

输出结果:

关于脚本语言还可以具备的其他特性,比如热更新,C# 同样可以支持。