首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#:沙箱和性能(MarshalByRefObject)

C#:沙箱和性能(MarshalByRefObject)
EN

Stack Overflow用户
提问于 2011-06-12 22:28:00
回答 3查看 1.8K关注 0票数 2

我已经用C#编写了一个非常基本的web服务器,它加载处理对配置文件中指定的特定域名的请求的自定义模块。定制模块被加载到一个新的AppDomain中,因为我需要能够动态地卸载它们(这也有利于安全性)。因为模块被加载到新的AppDomain中,所以所有参数和返回类型都是MarshalByRefObject。这可以很好地工作,我传递了一个从MarshalByRefObject继承的HttpRequest对象,并返回一个由web服务器发送回客户机的LinkedList。

所有这些都工作得很好,但是很多数据都是作为byte[]传递的,我相信MarshalByRefObject的代理将把所有字节从新的AppDomain复制到主AppDomain中,而不是直接访问它们。因此,如果我没弄错的话,如果其中一个模块会发送一个5MB的文件作为响应,那么5MB就会在模块中加载/生成,然后从模块AppDomain复制到主AppDomain,最后通过套接字发送回客户机。

所以,我的问题是:我能以某种方式绕过这个问题,这样它就不会在AppDomain之间复制这么多数据吗?或者有没有一种不使用MarshalByRefObject的更好的方法呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-06-13 06:16:59

我最终将SocketInformation传递给了新的AppDomain,并在那里(在新的AppDomain中)创建了一个新的socket对象。

在我的"Sandbox包装器对象“中,我有这个函数:

代码语言:javascript
复制
internal class Sandbox
{
    private AppDomain _AppDomain;
    private WebApplicationProxy _Proxy;

    public Sandbox(string assemblyFile)
    {
        _AppDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
        _Proxy = (WebApplicationProxy)_AppDomain.CreateInstanceAndUnwrap(
                                                    Assembly.GetExecutingAssembly().FullName,
                                                    "WebServer.WebApplication.Proxy");
        _Proxy.Initialize(assemblyFile);
    }
    public void SendResponse(Socket client, HttpRequest request)
    {
        SocketInformation clientInfo = client.DuplicateAndClose(Process.GetCurrentProcess().Id);
        _Proxy.GetResponse(clientInfo, request);
    }
}

在新的AppDomain“恢复”套接字中,我还不确定幕后到底发生了什么……代码如下:

代码语言:javascript
复制
internal class Proxy : MarshalByRefObject
{
    private AppController _AppController;

    public void Initialize(string assemblyFile)
    {
        Assembly asm = Assembly.LoadFile(assemblyFile);
        var q = from t in asm.GetTypes()
                where t.GetInterfaces().Contains(typeof(AppController))
                      && !t.IsAbstract && t.IsClass
                select t;
        foreach (Type t in q)
        {
            _AppController = (AppController)Activator.CreateInstance(t);
        }
    }

    public void SendResponse(SocketInformation clientInfo, HttpRequest req)
    {
        Socket client = new Socket(clientInfo);

        LinkedList<byte[]> toSend = _AppController.GetResponse(client, req);

        foreach (byte[] bytes in toSend)
            client.Send(bytes);

        client.Close();
    }
}

我不确定调用DuplicateAndClose或在新域中创建新的Socket对象时会发生什么细节,但到目前为止它工作得很好。

票数 2
EN

Stack Overflow用户

发布于 2011-06-12 22:32:48

字符串是按进程而不是按应用程序域的(出于性能原因)。如果传递的是html/xml (而不是二进制数据),则可以将api更改为使用String而不是byte []。您甚至可以在普通情况下支持字符串,在二进制情况下支持byte[]。

票数 3
EN

Stack Overflow用户

发布于 2011-06-13 06:28:13

如果这是.NET 4.0,使用Memory mapped file会是一个选择吗?

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

https://stackoverflow.com/questions/6322480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档