网站域名买卖,公司网页简介,做程序网站需要什么代码吗,电商网站的商品主图.NET学习资料
.NET学习资料
.NET学习资料 在 C# 编程领域中#xff0c;封送#xff08;Marshaling#xff09;和远程编程#xff08;Remote Programming#xff09;是两个极为重要的概念#xff0c;它们为开发者提供了与不同环境、不同进程或不同机器上的代码进行交互的…
.NET学习资料
.NET学习资料
.NET学习资料 在 C# 编程领域中封送Marshaling和远程编程Remote Programming是两个极为重要的概念它们为开发者提供了与不同环境、不同进程或不同机器上的代码进行交互的能力极大地拓展了应用程序的功能和适用范围。
一、C# 封送
一定义与作用
封送是指在托管代码如 C# 编写的代码由公共语言运行时 CLR 管理和非托管代码如 C、C 编写的代码没有 CLR 参与之间进行数据转换和传递的过程。不同编程语言和环境在调用约定、布局约定、基本数据类型大小、对象创建与销毁约定以及设计准则等方面存在差异。例如C# 中的char类型和 C 中的char类型在大小和编码方式上可能不同。因此需要封送来解决这些差异确保数据能够在不同环境之间正确传递和理解 。它就像是一座桥梁连接着托管世界和非托管世界使得两者能够进行有效的通信。
二常见的封送类型及处理方式
blittable 类型
像byte、short、int、long等及其无符号对应类型这些类型在托管和非托管代码之间传递时不需要特殊的封送处理因为它们在不同环境中的内存布局和表示方式是一致的可以直接进行数据传输。
非 blittable 类型
字符串类型在 C# 与非托管代码交互时若要将string封送到非托管函数可以使用Marshal.StringToHGlobalAnsi、Marshal.StringToHGlobalAuto、Marshal.StringToHGlobalUni等方法 操作完成后需调用Marshal.FreeHGlobal释放内存从非托管函数中取出string则可使用Marshal.PtrToStringAnsi、Marshal.PtrToStringAuto、Marshal.PtrToStringUni。例如当调用一个非托管的 C 函数该函数接收一个 ANSI 编码的字符串参数时就可以使用Marshal.StringToHGlobalAnsi将 C# 中的string转换为符合要求的非托管内存中的字符串形式。
数组类型对于byte[]或其他基础类型的数组可以使用Marshal.Copy方法实现从byte[]拷贝封送到非托管函数或从非托管函数拷贝封送到byte[] 。另外还可以采用固定内存直接传送byte[]的原始地址的方式这种方式省去了申请内存和拷贝的开销速度更快具体是使用GCHandle并指定GCHandleType.Pinned类型。假设需要将一个字节数组传递给非托管代码进行快速处理固定内存地址的方式就能提高数据传输效率。 委托类型从delegate封送到非托管函数可使用Marshal.GetFunctionPointerForDelegate从非托管函数中取出则使用Marshal.GetDelegateForFunctionPointer 。在封送到非托管函数时要确保垃圾回收器GC不会回收委托通常需要保持引用但不需要将其固定。比如在实现回调函数机制时就可能涉及委托类型的封送。
结构体类型在 C# 中按相同顺序和对应数据类型声明一个同样的struct只能使用基础类型和固定长度的数组并且标记StructLayout的LayoutKind.Sequential属性然后利用Marshal.StructureToPtr和Marshal.PtrToStructure进行封送。当与非托管代码进行结构体数据交互时这种方式能保证数据结构的正确传递。
三自动封送与手动封送
自动封送当 C# 声明的extern函数返回类型和参数类型中有托管类型如string、byte[]、委托等时CLR 会自动进行封送处理这大大节省了开发者编写封送代码的时间和精力。例如在调用一个非托管的 DLL 函数该函数的参数是一个字符串时C# 代码中无需额外编写复杂的封送代码CLR 会自动完成字符串类型的封送转换。 手动封送在某些特殊情况下自动封送无法满足需求就需要手动进行封送。比如当string的编码是 UTF - 8 之类的非 ANSI 非 UTF - 16 编码时必须手动进行封送并同时转换编码又或者委托转换成函数指针的操作比较耗时如果有频繁的对同一委托进行封送调用预存转换后的结果能够显著提升性能此时也需要手动进行封送处理。
二、C# 远程编程
一.NET Remoting 框架概述
.NET Remoting 是一种分布式处理框架它允许对象通过应用程序域与另一对象进行交互 可以看作是 DCOM 的一种升级并且很好地融合到了.NET 平台下。其核心优势在于提供了一种灵活且抽象的进程间通信方式使得开发者无需关注具体的客户端或服务器应用程序域也无需关心特定的通信协议就能实现不同应用程序域甚至不同机器上的对象之间的通信。
二主要组件
可远程处理的对象Remoteable Object这是需要在远程环境中被访问和调用的对象。它必须继承自MarshalByRefObject类以便能够跨越应用程序域进行通信。例如一个实现了业务逻辑的服务类希望被远程客户端调用其方法就可以让这个类继承MarshalByRefObject。
远程监听应用程序Remote Listener Application负责监听对远程对象的请求。它创建并注册通信通道同时注册远程对象使其能够被远程客户端发现和访问。比如在服务器端通过创建一个 TCP 或 HTTP 通道并将远程对象注册到该通道上等待客户端的连接请求。
远程客户端应用程序Remote Client Application向远程对象发出请求。客户端通过 Remoting 框架访问通道以获取服务器端对象的引用然后通过该引用调用远程对象的方法。在客户端代码中首先创建一个与服务器端对应的通道然后使用Activator.GetObject等方法获取远程对象的引用进而调用其公开的方法。
三通信原理与通道
通信原理在 Remoting 中客户端获取服务器端对象时得到的并不是实际的服务端对象而是它的引用这保证了客户端和服务器端对象的松散耦合同时优化了通信性能。客户端通过通道发送请求消息服务器端通过相应的通道接收请求并处理然后将结果通过通道返回给客户端 。整个过程就像是客户端和服务器端通过一条 “通信管道” 进行交互而这条 “管道” 就是通道。
通道类型主要支持 TCP传输控制协议和 HTTP超文本传输协议通道。使用 TCP 通道时数据以二进制形式传输效率较高适合在内部网络环境中使用而 HTTP 通道则基于 HTTP 协议数据以 SOAP简单对象访问协议格式传输具有更好的跨平台和跨网络环境的兼容性适合在 Internet 等复杂网络环境中使用。
四代码示例
定义远程对象
using System;
namespace RemoteObject
{public class MyRemoteObject : MarshalByRefObject{public MyRemoteObject(){}public int Add(int a, int b){return a b;}}
}服务器端代码
using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using RemoteObject;namespace RemoteServer
{class Program{static void Main(string[] args){// 创建TCP服务器通道端口号为8080TcpServerChannel channel new TcpServerChannel(8080);// 注册通道ChannelServices.RegisterChannel(channel, false);// 注册远程对象对象URI为MyRemoteObject激活模式为单例RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyRemoteObject), MyRemoteObject, WellKnownObjectMode.Singleton);Console.WriteLine(服务器已启动等待客户端连接...);Console.Read();}}
}客户端代码
using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using RemoteObject;namespace RemoteClient
{class Program{static void Main(string[] args){// 创建TCP客户端通道TcpClientChannel channel new TcpClientChannel();// 注册通道ChannelServices.RegisterChannel(channel, false);// 获取远程对象引用MyRemoteObject remoteObject (MyRemoteObject)Activator.GetObject(typeof(MyRemoteObject), tcp://localhost:8080/MyRemoteObject);// 调用远程对象的方法int result remoteObject.Add(3, 5);Console.WriteLine(调用远程方法结果: result);Console.Read();}}
}通过以上对 C# 封送和远程编程的介绍希望能帮助你深入理解这两个重要概念及其在实际开发中的应用。如果你对代码实现细节、原理有进一步的疑问或者想要了解更多相关应用场景欢迎随时交流。