用户登录  |  用户注册
首 页商业源码原创产品编程论坛
当前位置:PB创新网文章中心编程技巧Visual C++

实例解析C++/CLI程序进程之间的通讯

减小字体 增大字体 作者:佚名  来源:本站整理  发布时间:2009-03-16 20:37:26


  当程序执行时,服务端需要知道其用来监听客户端连接请求的端口号,在此,这个整数值通过命令行参数提供。一般来说,端口号在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中,在此是为了处理客户端在关闭套接字之前的过早结束。

  客户端套接字

  现在,让我们来看一下客户端程序(参见例2)。在连接到服务端之后,客户端将发送一对随机的整数,并且在发送下一对之前等待返回的结果。此处我们所看到的是服务端与客户端的同步通讯,客户端在接收到前一对值的结果之前,是不会发送另一对新值的。

  例2:

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

int main(array<String^>^ argv)
{
 if (argv->Length != 2)
 {
  Console::WriteLine("Usage: Client port message-count");
  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);
 }

 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);
 }

 int messageCount = 0;

 try
 {
  messageCount = Int32::Parse(argv[1]);
 }
 catch (FormatException^ e)
 {
  Console::WriteLine("Message count {0} is ill-formed", argv[1]);
  Environment::Exit(4);
 }

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

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

  /*4*/ clientSocket->Connect(ipEndpoint);

  NetworkStream^ netStream = gcnew NetworkStream(clientSocket);
  BinaryReader^ br = gcnew BinaryReader(netStream);
  BinaryWriter^ bw = gcnew BinaryWriter(netStream);

  int value1, value2;
  int result;

  Random^ random = gcnew Random;
  (int i = 1; i <= messageCount; ++i)
  {
   /*5*/ value1 = static_cast<int>(random->NextDouble() * 100);
   /*6*/ value2 = static_cast<int>(random->NextDouble() * 100);
 
   /*7*/ bw->Write(value1);
   /*8*/ bw->Write(value2);
   Console::Write("Sent values {0,3} and {1,3}",value1, value2);
 
   /*9*/ result = br->ReadInt32();
   Console::WriteLine(", received result {0,3}", result);
   /*10*/ Thread::Sleep(3000);
  }

  /*11*/ clientSocket->Shutdown(SocketShutdown::Both);
  Console::WriteLine("Notified server we're shutting down");
  /*12*/ clientSocket->Close();
  /*13*/ netStream->Close();
  Console::WriteLine("Shutting down client");
 }
 /*14*/ catch (SocketException^ e)
 {
  Console::WriteLine("Request to connect to {0} on port {1} failed"+ "\nbecause of {2}", ipAddress, port, e);
  Environment::Exit(5);
 }
}

  如同服务端一样,客户端取得一个IP地址,把它与端口号绑定以生成一个IPEndPoint,并连接到服务端,而服务端在此之前一直处于阻塞监听模式。
天极yesky

上一页  [1] [2] [3]  下一页

Tags:

作者:佚名

文章评论评论内容只代表网友观点,与本站立场无关!

   评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
PB创新网ourmis.com】Copyright © 2000-2009 . All Rights Reserved .
页面执行时间:15,312.50000 毫秒
Email:ourmis@126.com QQ:2322888 蜀ICP备05006790号