注册通行证 用户名 密码
  • 文章投稿
  • 博客
  • 论坛
  • 设为首页
  • 加入收藏
jztop.com网络技术
  • 首页
  • | iT新闻
  • | 操作系统
  • | 组网建网
  • | 网络安全
  • | 程序开发
  • | 办公一族
  • | 工具软件
  • | 网页制作
  • | 多媒体制作
  • | 网吧技术
  • | 服务器
  • | 专题教程
Vista | 软件评测 | 系统备份 | 优化 | 进程 | 聊天 | 病毒 | Linux | 黑客 | 防火墙 | 数据库 | Web开发 | Java | Word | 游戏 | 32位开发 | 移动开发
当前位置:首页 > 程序开发 > 32位开发 > C/C++ 内容正文:C++/CLI程序进程之间的通讯

C++/CLI程序进程之间的通讯

发布时间:2006-05-10 15:29:07 来源:天极开发 网友评论 0 条
  现在,把大型软件项目分解为一些相交互的小程序似乎变得越来越普遍,程序各部分之间的通讯可使用某种类型的通讯协议,这些程序可能运行在不同的机器上、不同的操作系统中、以不同的语言编写,但也有可能只在同一台机器上,实际上,这些程序可看成是同一程序中的不同线程。而本文主要讨论C++/CLI程序间的通讯,当然,在此是讨论进程间通讯,而不是网络通讯。

  简介

  试想一个包含数据库查询功能的应用,通常有一个被称为服务端的程序,等待另一个被称为客户端程序发送请求,当接收到请求时,服务端执行相应功能,并把结果(或者错误信息)返回给客户端。在许多情况中,有着多个客户端,所有的请求都会在同一时间发送到同一服务端,这就要求服务端程序要更加高级、完善。

  在某些针对此任务的环境中,服务端程序可能只是众多程序中的一个程序,其他可能也是服务端或者客户端程序,实际上,如果我们的数据库服务端需要访问不存在于本机的文件,那么它就可能成为其他某个文件服务器的一个客户端。一个程序中可能会有一个服务线程及一个或多个客户线程,因此,我们需小心使用客户端及服务端这个术语,虽然它们表达了近似的抽象含义,但在具体实现上却大不相同。从一般的观点来看,客户端即为服务端所提供服务的"消费者",而服务端也能成为其他某些服务的客户端。

  服务端套接字

  让我们从一个具体有代表性的服务端程序开始(请看例1),此程序等待客户端发送一对整数,把它们相加之后返回结果给客户端。

  例1:

using namespace System;
using namespace System::IO;
using namespace System::Net;
using namespace System::Net::Sockets;

int main(array<String^>^ argv)
{
if (argv->Length != 1)
{
Console::WriteLine("Usage: Server port");
Environment::Exit(1);
}

int port = 0;

try
{
port = Int32::Parse(argv[0]);
}
catch (FormatException^ e)
{
Console::WriteLine("Port number {0} is ill-formed", argv[0]);
Environment::Exit(2);
}

/*1*/ if (port < IPEndPoint::MinPort || port > IPEndPoint::MaxPort)
{
Console::WriteLine("Port number must be in the range {0}-{1}",
IPEndPoint::MinPort, IPEndPoint::MaxPort);
Environment::Exit(3);
}

/*2*/ IPAddress^ ipAddress =
Dns::GetHostEntry(Dns::GetHostName())->AddressList[0];
/*3*/ IPEndPoint^ ipEndpoint = gcnew IPEndPoint(ipAddress, port);

/*4*/ Socket^ listenerSocket = gcnew Socket(AddressFamily::InterNetwork,
SocketType::Stream, ProtocolType::Tcp);

/*5*/ listenerSocket->Bind(ipEndpoint);

/*6*/ listenerSocket->Listen(1);
/*7*/ Console::WriteLine("Server listener blocking status is {0}",
listenerSocket->Blocking);

/*8*/ Socket^ serverSocket = listenerSocket->Accept();
Console::WriteLine("New connection accepted");
/*9*/ listenerSocket->Close();

/*10*/ NetworkStream^ netStream = gcnew NetworkStream(serverSocket);
/*11*/ BinaryReader^ br = gcnew BinaryReader(netStream);
/*12*/ BinaryWriter^ bw = gcnew BinaryWriter(netStream);

try
{
int value1, value2;
int result;

while (true)
{
/*13*/ value1 = br->ReadInt32();
/*14*/ value2 = br->ReadInt32();
Console::Write("Received values {0,3} and {1,3}",
value1, value2);

result = value1 + value2;
/*15*/ bw->Write(result);
Console::WriteLine(", sent result {0,3}", result);
}
}
/*16*/ catch (EndOfStreamException^ e)
{
}
/*17*/ catch (IOException^ e)
{
Console::WriteLine("IOException {0}", e);
}

/*18*/ serverSocket->Shutdown(SocketShutdown::Both);
/*19*/ serverSocket->Close();
/*20*/ netStream->Close();
Console::WriteLine("Shutting down server");
}

  此处与套接字相关的功能由命名空间System::Net和System::Net::Sockets提供,并且需要在生成期间引用System.dll程序集。另外,因为通过套接字的通讯涉及到流,所以还要用到System:IO机制。

  当程序执行时,服务端需要知道其用来监听客户端连接请求的端口号,在此,这个整数值通过命令行参数提供。一般来说,端口号在0-65535范围内,而0-1023保留给特定的用途,因此,服务端可用的端口号就为1024-65535。

  在标号1中,通过IPEndPoint类中的MinPort和MaxPort这两个公共静态字段,就可得到特定系统上可用的端口范围。

  而在标号2中,可得到我们自己的主机名,并解析到一个IpHostEntry,可从中取得本机的IP地址。接下来在标号3中,用IP地址和端口号创建了一个IPEndPoint对象,其可为某个连接提供某种服务。

  在标号4中,创建了一个Internet传输服务托管版本的套接字,一旦它被创建,就应通过Bind函数(标号5)绑定到一个特定的端点。接下来,套接字声明其已经开始服务,并监听连接请求(标号6)。传递给Listen的参数表明了请求队列中连接挂起的长度,因为我们只有一个客户端,所以在此1就足够了。

  套接字默认以阻塞模式创建,如标号7中所示,这意味着,它会一直等待连接请求。

  当从客户端接收到连接请求时,阻塞的套接字就会被唤醒,通过调用Accept(如标号8),接受请求并创建另一个套接字,并通过此套接字来与客户端通讯。我们看到,此时的服务端有两个套接字:一个用于监听客户连接请求,而另一个用于与连接的客户端通讯。当然,一个服务端在同一时间,可与多个客户端进行连接,且每个客户端都有一个套接字。

  在这个简单的例子中,我们只关心请求连接的第一个客户端,一旦连接上了,便可关闭此监听连接请求的套接字(参见标号9)。
在标号10-12中,我们用最近连接的套接字,建立了一个NetworkStream,连同两个读写函数一起,便可以从套接字接收请求,并返回结果。
服务端在此无限循环,读入一对整数,计算它们的和,并把结果返回给客户端。当服务端探测到输入流中的文件结束标志时(由客户端关闭了套接字),会抛出EndOfStreamException异常,并关闭I/O流和套接字,服务结束。

  标号18中的Socket::ShutDown调用将同时关闭套接字上的接收和发送功能,因为我们的服务端只需告之一个客户端它的关闭,所以此函数调用有点多余,但是,在服务端要过早地结束的某些情况下,这种做法还是有用的。

  为何要捕捉IOException异常的原因在标号17中,在此是为了处理客户端在关闭套接字之前的过早结束。

 1/2    1 2 ›› ›|
相关文章
  • 清除不明进程msser 珊瑚QQ病毒防范技巧
  • C++的未来之路:C++0x概览
  • 利用VC++实现局域网实时视频传输
  • Visual C++打造Windows信使服务程序
  • PHP中通过Web执行C/C++应用程序
【评论】【收藏本文】【打印】【关闭】
上一篇文章:C++的未来之路:C++0x概览
下一篇文章:C++数据类型的属性与限制
讨论区
查看
已有 0 位对此新闻感兴趣的网友发表了看法
匿名发表
注册通行证 登陆
图文阅读推荐
推荐阅讯
  • Windows Socket1.1 程序设计
  • Visual C++ 入门精解-引言
  • 从C++到Java --理解面向对象是关键所在
  • VC++中利用磁盘序列号识别正版软件
  • C语言:超越C++下一代C++ —C++/CLI简介
  • C++启蒙之输入/输出
  • Visual C++ 入门精解-第三部分
  • C/C++中枚举类型(enum)的入门教程
  • 轻轻松松学习C++ 标准模板库STL
  • 明晰C++内存分配的五种方法的区别
阅读排行
  • 1.Borland 发布C++ Builder 2006 RAD 环境
  • 2.C/C++程序员应聘常见面试题深入剖析
  • 3.Visual C++常用数据类型转换详解
  • 4.C++中的 static 关键字
  • 5.利用VC++实现局域网实时视频传输
  • 6.浅谈C/C++内存泄漏及其检测工具
  • 7.英国投票否决C++/CLI 微软强攻ISO标准受挫
  • 8.VC++下用MSComm控件实现串口通讯
  • 9.伪随机数生成及在VC++中的实现
  • 10.VC++编程实现对波形数据的频谱分析
专题教程
  • 大话G游 专题:手机病毒揭密
  • ARP攻击防范与解决方案 路由故障处理手册
  • Picasa中文版_Picasa教程 专题:清除流氓软件
  • Firefox专题 seo搜索引擎优化专区
  • 重装Windows必知的事情 装机之必备软件大行动
病毒专杀栏
  • 杀毒软件反被病毒杀 连"救命"都不能喊
  • 金山ARP防火墙
  • 还原卡神话破灭“机器狗”病毒来势汹汹
  • cctv经济半小时:你的手机现在安全吗?
  • 新挂马方式开始流行 ARP挂马称雄局域网
  • 木马和病毒清除的通用解法
  • IP地址不再冲突 查找ARP攻击者元凶
  • 教你几招识别和防御Web网页木马
  • 分析:封杀BT只是暂时的止痛药
  • QQ爆危险漏洞,“QQ游戏邀请大盗”邀请你玩病
关于我们 | 诚聘英才 | 联系我们 | 版权声明 | 网站大事 | 网站地图 | 意见建议
CopyRight 2005-2007 Jztop.Com 版权所有 未经许可 请勿转载