`
jiq408694711
  • 浏览: 36621 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

C#程序间通信的各种途径及解析

 
阅读更多
原文地址:C# 程序间通信的各种途径及解析作者:留心驿站
一、开篇
程序间通信的主要目的是实现多台计算机(也可以是同一台)中应用程序之间的数据共享与信息交换。在不同的计算机系统中,它们之间要通过网络之间的协议才能实现数据共享与信息交换;在同一台计算机系统中,它们之间只需一定的通道就能实现数据共享与信息交换。在不同计算机系统和同一计算机系统的程序通信中,既有很多相同之处,也有各自的特点。程序间通信都要靠一定的通道(pipe)来实现,其中的通道多种多样,各俱特色。
为了充分认识和掌握程序间通信及其相应的实现技术,本文对各种通信方法进行讨论。包括每种方法的原理和实现等。

二、各种通信途径及实现
首先,程序间相互独立,它的运行环境不为别的进程所改变。
I.[socket]
SOCKET编程是一种典型的会话编程方式,类似于老师家访,敲门----有人开门----进去----交流----出门。它适用于client/server通信方式,也适用于点对点通信方式。
下面分别介绍服务端和客户端的具体任务。
这里介绍TCP的过程。
(1)服务端
服务端首先创建一个套接字,使用socket()调用;然后使用bind()将该套接字与本地IP和某一端口相关联(该端口可以是空闲的也可以是非空闲的,具体的可以参阅笔者的《对端口截听的实现》这篇文章)。使用listen()让套接字等候进入连接,然后用accept()使套接字作好接受客户连接的准备。当连接请求到来后,被阻塞服务进程的accept()函数生成一个新的套接字与客户套接字建立连接,并向客户返回接收信号。用read()来读入数据,用write()来向发送进程写回一些数据,如确认信息或回显信息。
(2)客户端
客户进程也是先创建一个套接字,用socket()调用,然后客户向服务进程发出连接请求,通过调用connect()可以建立一个端的连接,连接成功后用write()向服务端发送数据,用read()读取服务端返回的数据。
这种方式隐含了在建立client/server间通信的非对称性。client/server模型工作时要求有一套为客户机和服务器所共识的惯例来保证服务器能够被提供(或被接受),这一套惯例包括了一套协议,它必须在通信的两头都被实现。根据不同的实际情况,协议可能是对称的或是非对称的。在对称的协议中,每一方都有可能扮演主从角色;在非对称协议中,每一放则是从机。例如终端仿真TELNET是对称协议,HTTP是非对称协议。无论具体的协议是对称的还是非对称的,当服务被提供时必然存在客户进程和服务进程。
这种通信方式适用于单个计算机系统,也适用于多个计算机系统。
[cpp:nogutter] view plaincopyprint?
WSADATA wsaData;
WORD version = MAKEWORD(2, 0);
int ret = WSAStartup(version, &wsaData);
if(ret != 0)
TRACE("Initilize Error!/n");
m_hSocket = socket(AF_INET, SOCK_STREAM,0);
m_addr.sin_family = AF_INET;
m_addr.sin_addr.S_un.S_addr = INADDR_ANY;
m_addr.sin_port = htons(m_nPort);
int ret = 0;
int error = 0;
ret = bind(m_hSocket, (LPSOCKADDR)&m_addr, sizeof(m_addr));
if(ret == SOCKET_ERROR){
TRACE("Bind Error: %d /n", (error = WSAGetLastError()));
return ;
}
ret = listen(m_hSocket, 2);
if(ret == SOCKET_ERROR){
TRACE("Listen Error: %d /n", (error = WSAGetLastError()));
return ;
}
SOCKET s = accept(m_hSocket, NULL, NULL);
if(s == SOCKET_ERROR){
TRACE("Accept Error: %d /n", (error = WSAGetLastError()));
return ;
}
char buff[256];
ret = recv(s, buff, 256, 0);
if(ret == 0 || ret == SOCKET_ERROR ){
TRACE("Recv data error: %d/n", WSAGetLastError());
return ;
}
char buf[]="hello";
send(s, buf, str.GetLength(), 0);

II.[file]
这种方法很原始,使用率也很少,而且占用磁盘空间。利用文件作为程序间通信的通道,程序A向一文件写入数据,程序B通过读取这个文件中的数据从而与程序A进行通信,同时这一过程也可以是反向的。这种方法使用的前提是运行程序的用户需要具有对磁盘读/写的权限。
|A.WriteFile------>fileA<------B.ReadFile(check every <time>)
|A.ReadFile(check every <time>)----->fileB<-----B.WriteFile
[c-sharp:nogutter] view plaincopyprint?
//A
int buff=0;
ofstream Table;
Table.open("c://temp.txt");
Table<<buff<<endl;
Table.close();
//B
int buff=1;
for(;;)
{
ifstream Table;
Table.open("c://temp.txt");
Table>>buff;
Table.close();
if(buff==0){
printf("Operation code equal 0");
//...
return;
}
sleep(10);
}

这种方法适用于单个计算机系统也适用于多个计算机系统。用这种方法在多个计算机系统间进行控制和数据交换,可以将这个文件放与一计算机上,对方建立空连接,COPY此文件到本地,进行读取。当然也还有别的很多方法。
III.[signal]
这种方法仅用于进程控制,不能进行数据交换。例如在发生非法内存访问、执行无效指令、某些按键(如CTRL+C,DEL等)等都会产生一个信号,其他程序调用有关的系统调用或用户自定义的处理过程进行处理。
信息处理的系统调用是signal,它的原型是void ( *signal( int sig, void (__cdecl *func) ( int sig [, int subcode ] )) ) ( int sig );这个函数可以让一个进程选择很多方法中的一种去处理操作系统返回的中断讯号。
根据类似的思路,我们也可以在多个程序间利用“信号”进行程序间的通信。
这种方法的关键是产生信号。可以通过keybd_evnet()产生信号,这个函数能够起到模拟键盘输出的作用,它的函数原型是VOID keybd_event(BYTE bVk,BYTE bScan,DWORD dwFlags,DWORD dwExtraInfo);vVk是一个虚拟键码,bScan是扫描码,对应相应的键。
这种方法适用于单个计算机系统。
IV.[pipe]
管道(PIPE)是一种简单的进程间通信(IPC)机制,分为无名管道和有名管道两种。命名管道可以在同一台机器的不同进程间以及不同机器上的不同进程间进行双向通信(使用UNC命名规范)。管道的最大好处在于:它可以象对普通文件一样进行操作,它的操作表示符HANDLE,也就是说,它可以使用ReadFile,WriteFile函数进行与底层实现无关的读写操作,用户根本就不必了解网络间/进程间通信的具体细节。
无名管道实际上是内存中的一个临时存储区,由系统安全控制,并且独立于创建它的进程的内存区。管道对数据采用先进先出的方式管理,并严格按顺序操作,管道不能被搜索,管道中的信息只能读一次。无名管道只是在父子进程之间或者一个进程的两个子进程之间进行通信的。它是单向的。无名管道其实是通过用给了一个指定名字的有名管道来实现的。
有名管道的操作和无名管道类似。
管道的创建用createpipe()函数,用readfile()、writefile()对其进行操作。
[cpp:nogutter] view plaincopyprint?
SECURITY_ATTRIBUTES a;
HANDLE hReadPipe,hWritePipe;
CreatePipe(&hReadPipe,&hWritePipe,&a,0);
unsigned long lBytesRead;
char Buff[1024];
int ret;
while(1)
{
ret=PeekNamedPipe(hReadPipe,Buff,1024,&lBytesRead,0,0);
if(lBytesRead)
{
ret=ReadFile(hReadPipe,Buff,lBytesRead,&lBytesRead,0);
if(!ret) break;
}
else
{
//lBytesRead=...;
if(lBytesRead<=0) break;
ret=WriteFile(hWritePipe,Buff,lBytesRead,&lBytesRead,0);
if(!ret) break;
}
}

V.[MQ]
消息通信方式以消息缓冲区为中间介质,通信双方的发送和接收操作均以消息为单位。在存储器中,消息缓冲区被组织成队列,通常称为消息队列(MQ)。消息队列是独立于生成它的进程的一段存储区,任何具有正确访问权限的进程都可以访问消息队列,它非常适用于在进程间交换短消息。
其中,每条消息有类型编号分类。消息队列在创建后将一直存在,直到使用相关的调用删除它为止。
VI.[共享储存段(SM)]
共享储存段通信(shared memory)允许多个进程在外部通信协议或同步/互斥机制的支持下使用同一个内存段作为中间介质进行通信,它是一种很有效的数据通信方式。
在进行通信之前,先创建一个共享内存段,然后进行映射和分离操作。同时可以根据需要改变共享内存段的存取权限以及其他的一些特征。

☆对于下面的集中通信方式,就要提到“中间件(Middleware)”。
中间件是一类软件,它对应用程序隐含了实际网络和通信协议的细节。高级编程接口帮助开发者在不同的环境中创建应用程序,而不需要对将使用的网络和通信协议有更多的了解。

正常情况下,中间件在使用不同网络通信协议的客户机/服务器环境。它可以对客户机/服务器应用隐藏协议,从而使开发人员集中精力于改进应用程序,而不是开发通信接口。
中间件产品隐藏了前端应用程序和后端应用程序的区别。中间件层包括通用应用程序和流行应用程序的应用程序编程接口(API)之间的翻译功能。例如,Microsoft的开放式数据库连接(ODBC)标准提供后端数据库系统操作的通用功能。前端应用程序写入ODBC,并利用它的功能。ODBC 隐藏了不同厂商的SQL实现的区别。Microsoft以一组Microsoft Windows驱动程序的形式提供ODBC,以提供对Microsoft Access、Microsoft Excel、Microsoft SQL Server、FoxPro、Btrieve,dBASE,Borland Paradox、IBM DB2、DECRdb和Oracle等格式产生的数据的访问。ODBC是为了使Windows成为客户访问后端数据库的标准而设计的。
□用户需要访问许多不同的后端服务器上的服务。
□后端服务器可以使用不同的操作系统,并需要不同的通信协议。
□后端数据库服务器有不兼容的SQL命令集,它使用户和程序员很难从一个系统转到另一个系统。
□限制用户只能使用某种特定的访问后端服务的应用程序现在已经不现实。用户需要从不同的应用程序来访问服务。
□新的模型是为了使用户在多厂商环境使用多种协议在任何前端来访问任何后端服务。
在多协议、多厂商环境,通常一个程序员需要编写应用程序,来与每个协议和支持系统进行工作。使用中间件,程序员只需简单地编写到中间件的接口,而由中间件处理所有多协议、多厂商问题。有三种类型的中间件:远程过程调用(RPC)、会晤(conversations)和消息传递系统。它们都能很好地隐藏通信过程,以及与它们进行操作的系统差异。
VII.[RPC]
Remote Procedure Call(PRC)
一个远程过程调用是在网络上一个计算机系统对另一计算机系统的请求。RPC保持了中间件在不同网络平台和通信协议上工作的性质。基本上,一个PRC就是一台计算机向另一台计算机发出的直接请求。它是一种请求/回答的过程,这时请求放等待一个回答,这意味着PRC通常是在面向连接界面上发生的一种实时呼叫。
RPC机制强制通信的两个应用程序必须同时处于运行状态。做远程调用时,两者必须先建立连接,而且通讯链路质量对它的效果影响很大。
它的工作方式是:当一个应用程序A需要与远程的另一个应用程序B交换信息或要求B提供协助时,A将在本地产生一个请求,通过通讯链路,同志B接收信息或提供相应的服务,B完成相关处理后将确认信息或结果返回给A。
PRC的优点是应用程序采用调用/返回方式通讯,拥有很高的潜在效率,但需要应用程序间的紧密耦合,通讯线路必须在通信期间一直保持良好的状态,而且必须进行大量的底层通讯的编程工作。
VIII.[conversations]
会晤(conversations)是逻辑连接的两个或多个系统之间的连续会话,同RPC不同,在分布式环境,会晤可能会重叠执行。出于这个原因,对需要在多个地方必须完全同步地完成,修改分布式数据库的工作,会晤是非常必要和有益的。IBM的高级程序对程序通信(APPC)实现了会晤。用于实现会晤的OSI标准也已出现。Covia Technologies(Rosemont,Illinois)的通信集成器(CI,Communication Integrator)是具有会晤的中间件的另一个例子、它可以在大型计算机、中型机和台式机上运行。
IX.[MQSeries消息队列]
为了简化应用程序间的通信,使得通信具有较高的可靠性,又保证实现的简单性,中间件技术是我们的首选,IBM公司的MQSeries就是基于这种技术的产品。MQSeries是一种独立的通信软件,应用程序只需将任务提交给该软件,就可以由该软件自动去完成信息的传递工作。
例如:
应用程序A
|
|
放入|消息
|
|

MQSeries接口----------------
∧ |
| |
| |唤醒
读取|消息(于Q1中) |
| |
| |
应用程序B(无论本地还是远程)<-----
应用程序间的消息传递是通过队列来实现的,是间接的,所以即使B没能正常运行时,A仍然能正常运行,而且,消息还可以唤醒B。
可见,MQSeries的优点是可以确保信息是永久的、可恢复的,确保信息传递的安全性,确保信息的成功发送且只发送一次,同时,还可以使各应用程序可以独立的正常运行。
无论是共有的还是私有的队列,都是用MQOpenQueue()打开,MQOpenQueue函数用来打开一个用来发送消息或是读取消息的队列。它的原型是HRESULT APIENTRY MQOpenQueue( LPCWSTR lpwcsFormatName, DWORD dwAccess, DWORD dwShareMode, LPQUEUEHANDLE phQueue );其中,lpwcsFormatName是用户指定的指向队列的format name字符串,这个format name可以是public,private,或者是direct format。dwAccess是由用户指定的应用程序使用队列的方法,可以是peek,send,receive。当队列打开以后这个设置就不能被更改。dwAccess有三种模式:MQ_PEEK_ACCESS/MQ_SEND_ACCESS/MQ_RECEIVE_ACCESS。dwShareMode是由用户指定的队列的共享模式,分为:MQ_DENY_NONE和MQ_DENY_RECEIVE_SHARE,MQ_DENY_NONE是默认值,允许任何人使用,如果dwAccess设置成了MQ_SEND_ACCESS,那么在此就必须设置成MQ_DENY_NONE;MQ_DENY_RECEIVE_SHARE限制了从此队列读取消息的进程。如果这个队列已经被别的进程打开用来接收消息,那么将返回MQ_ERROR_SHARING_VIOLATION,MQ_DENY_RECEIVE_SHARE仅适用于当dwAccess设置成MQ_RECEIVE_ACCESS或MQ_PEEK_ACCESS的时候。phQueue是输出的已打开的队列的句柄。
然后可以用MQSendMessage()/MQReceiveMessage()等函数进行具体操作,在此不多熬述。
三、结束语
技术是一点一滴积累起来的,对任何知识点的系统性掌握很有必要也很有用。
各种通信的实现技术都具有自己的特点和使用范围,管道、消息队列、共享内存等技术最适用于同一计算机系统内部的进程间通信,以保证高效率。而远程过程调用、Socket会话编程、MQSeries则最适用于远程的应用程序之间通信,可以简化通信的编程,当然也保证通信的可靠性。尤其是MQSeries,它是一个比较完善的中间件产品,为许多的信息系统所选用。
对各种通信技术的合理搭配使用,常常能起到事半功倍的作用。
分享到:
评论

相关推荐

    C#USB通信.rar_C# USB 通信_USB通信_c#USB通信_newxw4_usb

    总之,C#为USB通信提供了良好的支持,通过使用适当的库和API,开发者可以轻松地实现与各种USB设备的通信。提供的压缩包资源提供了实际操作的例子,是学习和掌握这一技能的有效途径。在实际应用中,确保遵循最佳实践...

    C#MFC串口通信实现

    在本文中,我们将深入探讨如何在C#环境中利用MFC(Microsoft Foundation Classes)窗体应用实现...这为开发者提供了一种构建高效、灵活的串口通信系统的途径,无论是在C#的纯Windows应用程序还是与MFC结合的场景中。

    用C#编的永宏通讯协议类,通俗易懂,希望对大家有所帮助

    总的来说,C#实现的永宏通讯协议类为开发者提供了一个便捷的途径,使得他们能够在C#环境中快速搭建与永宏协议设备交互的程序。通过理解和运用这个类,不仅能够提升项目的开发效率,也能保证通信的稳定性和可靠性。...

    C#SuperSocket服务端与客户端通信实例

    本教程将深入探讨如何使用C#编程语言以及SuperSocket库来构建一个高效、稳定的服务器端和客户端通信模型。SuperSocket是一个轻量级且易于使用的.NET Socket服务端开发框架,它为开发者提供了构建自定义网络应用的...

    C#超级通信调试工具源码

    《C#超级通信调试工具源码解析》 在IT领域,C#是一种广泛使用的编程语言,尤其在.NET框架下,它的应用无处不在。本文将深入探讨“C#超级通信调试工具”的源码,帮助开发者了解如何利用C#进行高效且稳定的通信调试。...

    C#与Omron PLC通讯HOSTLINK C-MODE

    总结起来,C#与Omron PLC的HOSTLINK C-MODE通信涉及了串口通信、协议解析、错误处理等多个技术点。开发者需要对HOSTLINK协议有深入理解,同时熟悉C#的串口编程,才能构建出高效、稳定的通讯系统。提供的压缩包文件应...

    C# 程序 设计 教程 电子 PPT

    在本"C#程序设计教程"电子PPT中,我们涵盖了多个关键主题,这些主题对于深入理解和熟练运用C#编程语言至关重要。以下是对每个章节主要内容的详细解析: **第七章:继承和接口** 这一章深入探讨了面向对象编程的核心...

    c#100个经典小程序

    11. **委托与事件**:委托和事件是C#中的事件驱动编程机制,小程序将展示如何使用它们来实现组件间的通信。 12. **反射**:反射是C#中强大的动态类型功能,可以用来在运行时获取类型信息和调用方法,小程序会讲解...

    C#千千静听控制程序(附加源代码)

    《C#千千静听控制程序的深度解析与实践》 C#编程语言以其丰富的类库和高效性能在IT行业中占据一席之地,尤其在Windows应用程序开发领域,它更是广泛被采用。本项目名为“C#千千静听控制程序”,通过C#实现了对...

    C#写的局域网聊天程序(客户端对客户端)

    在本文中,我们将深入探讨如何使用C#语言构建一个局域网聊天程序,该程序能够实现客户端对客户端的通信,类似腾讯QQ的功能。这涉及到C#编程基础、网络编程概念以及TCP/IP协议的理解。 首先,C#是一种面向对象的编程...

    FANUC机床信息读取(C#)中文函数说明 C++可用.zip

    这个压缩包可能是为开发者准备的,帮助他们编写程序来与FANUC机床进行通信和数据交互。 描述中提到的"C++中文文档"和"C#,C++函数说明"暗示了压缩包内包含的资源不仅有代码示例,还有中文语言的文档,这对于中文用户...

    c#串口实现

    在C#编程环境中,串口通信是连接硬件设备和软件应用程序的重要途径,广泛应用于工业控制、数据采集、物联网设备交互等多个领域。本教程将详细解析如何在C#中实现串口程序,以及如何使用虚拟串口工具和串口调试助手...

    魔兽世界模拟器C#源码

    《魔兽世界模拟器C#源码解析》 在IT领域,游戏模拟器是一个备受关注的话题,尤其是对于游戏开发者和编程爱好者来说。本文将深入探讨一个由国外朋友开发的魔兽世界模拟器,其主要编程语言为C#。这个项目不仅为我们...

    C# IC卡读写源码(纯代码,无封装)

    在C#中进行IC卡操作,通常涉及到对智能卡硬件接口的编程以及对卡片内数据的解析和处理。 描述中提到,这个源码是“纯代码,无封装”,意味着它可能没有被封装成库或类,而是直接提供原始的函数和方法,这可能需要...

    C# 百度地图

    在IT行业中,C#是一种广泛使用的编程语言,尤其在Windows应用程序和游戏开发中扮演着重要角色。...在开发过程中,不仅要掌握API的使用,还要理解C#编程技巧,以及网络通信、数据解析和UI设计等相关知识。

    c++,c#程序实例集合

    在这个"C++,c#程序实例集合"中,我们可以期待看到各种C#编程的实际应用示例。这些实例将帮助初学者更好地理解C#语言的核心概念,同时也为有经验的开发者提供了一个实践和学习新技巧的平台。C#程序实例通常涵盖以下...

    C#实现WEB服务器

    Socket提供了一种进程间通信机制,允许数据在两个程序之间通过网络进行交换,无论这些程序是否运行在同一台计算机上。在本例中,服务器使用Socket监听特定端口(如8080),接收来自客户端的连接请求,并通过Socket与...

    C#读取音频时间

    总的来说,C#中获取音频文件如MP3的播放时间长度可以通过多种途径实现,如使用NAudio、DirectX的DirectShow.NET库,甚至在需要的情况下,结合网络或串口通信将这些信息传递出去。这些方法为音频处理提供了丰富的可能...

    hj212-master_hj212解析器_hj212-master_hj-212java_212_212协议解析demo

    在信息技术日益发达的今天,各种数据通信协议应运而生,其中HJ212协议作为一种广泛应用于环保领域的通讯协议,具有重要的实用价值。本篇文章将围绕"HJ212-master_hj212解析器_hj-212java_212_212协议解析demo"这一...

    C# QQ源码.rar

    《C# QQ源码解析与应用探讨》 在IT领域,源码的分析与学习是提升编程技能的重要途径。本文将深入探讨"C# QQ源码"这一主题,旨在帮助开发者理解C#语言在构建类似QQ这样的即时通讯软件中的应用。通过对源码的解读,...

Global site tag (gtag.js) - Google Analytics