在忍无可忍的情况下,我终于抛弃了remoting

remoting最讨厌的就是有个绑定ip问题,如果绑定ip,那么只能绑定一个,那么如果机器是多网卡,则只能用绑定的这个ip访问。

这位说了可以绑定机器名啊。

绑定机器名的话,如果服务器是内网的就不行了。

 

举个例子吧,如果一个服务器是内网,如果绑定路由器的外网ip,并在路由器做映射,那么外网是可以通过外网ip访问,而且路由器映射端口必须和remoting的端口一样才行,但这样的话局域网内通过内网ip就连不上了。

如果绑定机器名,内网通过机器名可以,外网就不行了,即使在路由器上映射端口也不行,可以通过sniffer软件看到,外网可以连接上remoting的服务器,但是却不能用。

原因就在于remoting在开始的连接头就有个ip的验证,你可以看到外网客户发送的remoting连接头有比如202.102.128.68:6666这样的,而返回的信息中包含192.168.0.8:6666这样的,就是这样虽然能连接但是对不上号。

remoting坑爹就坑爹在这里,他对于连接的验证放在这种坑爹的地方。

 

据说有种办法可以改变什么传输链的,可以改变这remoting的连接头,但是我觉得没必要了,为什么呢,因为我本来用remoting就是为了方便,可以不用自己去处理tcp连接了,还有个远程对象可以用,但现在反而比自己处理tcp连接还麻烦了。于是我决定毅然抛弃remoting,用tcpclient自己搞定。

本以为很麻烦的,结果却没有那么麻烦,远程对象嘛,自己反射就行了,效果是一样的。就是多加了一个序列化反序列化的过程。

就是tcp部分,就是麻烦一点,得很仔细的处理,主要是如何协商和处理异常,因为一个不小心,服务器的程序就崩溃了,所以主要就是协商和异常处理,要让程序很皮实才行,不能动不动就崩溃,也不能造成内存只升不降,也不能造成莫名其妙的100%cpu占用,这就是remoting的好处,tcp协商,异常处理m$都给做好了,你怎么搞服务器程序都不会崩溃,很皮实很皮实的,自己搞一点考虑不周就崩溃。

当搞定了tcp的协商和异常处理后,发现了反射加载了dll却不释放的问题,最后用appdomain,appdomain是个好东西呀,他不光是可以加载和卸载dll,而且,dll一点进了appdomain,那么就没有崩溃这一说了,这样的话dll怎么搞都无所谓了,顶多会返回一个“调用的目标发生异常“的信息,而不像普通程序那样,一点异常没处理,整个程序就崩溃。

最后给通信加入了rsa+aes的加密,这样,remoting的优势荡然无存。

 

最后效果是这样的,服务器程序是一个windows服务,他里面是空的,基本就是一个tcplistener+反射的一个执行器,客户端连接服务器,通信过程用rsa+aes加密,然后客户端传输一个byte[],这个byte[]是一个dll,然后服务器开一个appdomain,里面assembly直接load这个byte[],连.dll文件都不会有,全在内存中,客户端发送指令,然后appdomain中直接inoke,结果返回给客户端。当客户端结束通信后,服务器就appdomain.unload释放掉。

 

这样以来,服务器端就是一个执行器,通用的,他几乎不用再去改变什么,也就无需去升级,无论想具体执行什么样的功能,全在客户端的dll中改就可以了,无论dll中具体方法怎么改怎么加,反正方法名都作为字符串传过去,无论dll中的方法有什么样的参数和数量,都是object[]的数组,无论返回值是什么玩意,都是object,都不用管,序列化成byte[]传回来处理就行了。这样服务器就以不变应万变了。如果没有反射的话,服务器就得写死了,每改动一点服务器程序都得重新编译和安装了。

 

最近老是遇到内存释放问题,说.net不用管释放完全就是一句屁话,很明显的,比如不用appdomain,那么程序运行8兆左右,一个客户连进来,30几兆,但是客户走了还是30几兆,又一个客户进来,50几兆,走了还50几兆,如此80几兆100几兆,不降了,即使开个线程定时gc.collect()也没用,还是不降。这样一会就不能用了。但是用了appdomain后,客户来了多,走了程序能基本稳定在30来兆左右,虽然还是会每次都增加一点,但是就可以接受了,再配合一个定制gc.collect()的线程,就可以用了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
如果你需要在 .NET Standard 2.0 中使用 Remoting 库,可以按照以下步骤进行: 1. 在 Visual Studio 中创建一个 .NET Standard 2.0 类库项目。 2. 右键点击项目,选择“管理 NuGet 程序包”。 3. 在 NuGet 程序包管理器中搜索“System.Runtime.Remoting”并安装。 4. 在代码中使用 Remoting 相关的命名空间,例如 System.Runtime.Remoting.Channels、System.Runtime.Remoting.Messaging 等。 5. 编写 Remoting 服务端和客户端的代码,分别继承 MarshalByRefObject 类,并实现相应的接口。 以下是一个简单的示例代码: ```csharp // 定义远程接口 public interface IRemoteService { string SayHello(string name); } // 实现远程服务 public class RemoteService : MarshalByRefObject, IRemoteService { public string SayHello(string name) { return "Hello, " + name + "!"; } } // 服务端启动代码 public static void StartServer() { ChannelServices.RegisterChannel(new TcpChannel(1234), false); RemotingConfiguration.RegisterWellKnownServiceType( typeof(RemoteService), "RemoteService", WellKnownObjectMode.Singleton); } // 客户端调用代码 public static void CallServer() { var url = "tcp://localhost:1234/RemoteService"; var remoteService = (IRemoteService)Activator.GetObject(typeof(IRemoteService), url); var result = remoteService.SayHello("world"); Console.WriteLine(result); } ``` 需要注意的是,Remoting 在 .NET Standard 中的支持是有限的,不支持一些高级特性,例如对象激活和远程事件等。此外,Remoting 已经被官方宣布为过时技术,不再被推荐使用。如果需要实现跨平台的远程通信,建议使用更加现代化的技术,例如 gRPC 或 RESTful API。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值