我已经用C#编写了一个非常基本的web服务器,它加载处理对配置文件中指定的特定域名的请求的自定义模块。定制模块被加载到一个新的AppDomain中,因为我需要能够动态地卸载它们(这也有利于安全性)。因为模块被加载到新的AppDomain中,所以所有参数和返回类型都是MarshalByRefObject。这可以很好地工作,我传递了一个从MarshalByRefObject继承的HttpRequest对象,并返回一个由web服务器发送回客户机的LinkedList。
所有这些都工作得很好,但是很多数据都是作为byte[]传递的,我相信MarshalByRefObject的代理将把所有字节从新的AppDomain复制到主AppDomain中,而不是直接访问它们。因此,如果我没弄错的话,如果其中一个模块会发送一个5MB的文件作为响应,那么5MB就会在模块中加载/生成,然后从模块AppDomain复制到主AppDomain,最后通过套接字发送回客户机。
所以,我的问题是:我能以某种方式绕过这个问题,这样它就不会在AppDomain之间复制这么多数据吗?或者有没有一种不使用MarshalByRefObject的更好的方法呢?
发布于 2011-06-13 06:16:59
我最终将SocketInformation传递给了新的AppDomain,并在那里(在新的AppDomain中)创建了一个新的socket对象。
在我的"Sandbox包装器对象“中,我有这个函数:
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“恢复”套接字中,我还不确定幕后到底发生了什么……代码如下:
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对象时会发生什么细节,但到目前为止它工作得很好。
发布于 2011-06-12 22:32:48
字符串是按进程而不是按应用程序域的(出于性能原因)。如果传递的是html/xml (而不是二进制数据),则可以将api更改为使用String而不是byte []。您甚至可以在普通情况下支持字符串,在二进制情况下支持byte[]。
发布于 2011-06-13 06:28:13
如果这是.NET 4.0,使用Memory mapped file会是一个选择吗?
https://stackoverflow.com/questions/6322480
复制相似问题