113E博章

       登录 /注册
首页 一算子网 发布
分类 :c++/vc

用Socket接口实现网络异步通信 C+/VC

[ 2008-7-30 22:43:00 | 发表者 : zihe ]


用socket接口实现网络异步通信

  马爱民

  vc ++ 4.1以上版本的开发环境提供了socket接口,可以方便地进行网络通信。本文是在一个应用程序中利用socket接口实现异步通信,由于在异步通信状态下,服务端和客户端主控程序在等待信息时可以完成其他工作,因此具有更广阔的应用领域。

  1.建立应用程序框架

  为了便于说明程序之间的相互关系,假设已用vc ++的appwizard建立了单文档类型的应用程序框架,项目名为asock,它包括以下几个文件:

  asockapp.h asockapp.cpp

  mainfraim.h mainfraim.cpp

  childview.h childview.cpp

  下面在上述程序框架的基础上编写一个能进行异步通信的应用程序。

  2.流式套接字通信原理

  流式套接字因其可靠性高而得到广泛的应用。其通信原理为:服务端和客户端都必须建立通信套接字,而且服务端应先进入监听状态,然后客户端套接字发出连接请求,服务端收到请求后,建立另一个套接字进行通信,原来负责监听的套接字仍进行监听,如果有其他客户发来连接请求,则再建立一个套接字。默认状态下最多可同时接收5个客户的连接请求,并建立通信关系。

  3.定义mysocket类

  本例中为了实现套接字的网络异步通信,通过异步套接字类casycnsocket派生出两个新类。代码的生成可以利用classwizard来建立程序框架,给两个派生类取名为mysocket和servesocket,生成时使用的基类为casycnsocket,并可将它们放在同一组文件中(本例是放在mysocket.h和mysocket.cpp中)。接着在classwizard中为mysocket类加入onaccept()和onreceive()两个函数;为servesocket类加入onreceive()函数。注意,这些函数都是重载函数,不能随便给其命名,加入函数的方法是:在classwizard的object ids窗口中选中最后一行,然后在message窗口中选择相应的函数即可。

  两个派生类的功能是:mysocket类用于在服务端和客户端建立套接字,分别用于监听和通信;servesocket类用于在服务端建立通信套接字,它是在服务端监听到连接请求后才建立的,因此本例中将它作为mysocket类的成员变量。为了使服务端能响应多个客户的请求,可以建立5个servesocket类型的套接字,并设立一个记录器,记录已经收到的请求个数,该记录器在mysocket的构造函数中被置为0。

  完成异步通信的关键在于上述三个重载函数,它们从网络中传来信息时,可以被自动调用,以完成接收工作。在本例中,onaccept()函数在收到连接请求后,会向客户发出一个代表其序号的信息;两个onreceive()函数都进行提示,并在确认后将收到的信息发送回去。上述两个派生类的源代码在网上,网址为www.pccomputing.com.cn。

  4.完成服务端或客户端的设置

  通过菜单项完成的设置工作可以有多种安排方法,本例为了便于显示,将设置工作安排在cchildview类中。首先用资源编辑器在主菜单中增加server和client两个选项,并定义它们的id,然后用classwizard在cchildview类中增加对这两个id的响应函数,并在其中分别创建套接字后进入监听或开始连接。为了便于观察工作进程,可在其中增加相应的输出语句,另外,在childview.h和childview.cpp文件前面必须有#include "mysocket.h"语句。

  为了简化程序,本程序直接写入服务主机的ip地址,因此,本程序在使用时,服务端是指定的,不能随便改变,但客户端的位置不受限制。

  5.程序的使用

  本程序可以在同一网络中的不同主机之间进行异步通信。以两台主机为例,首先在指定的主机上启动本程序,并在菜单中选择server选项,使程序进入监听状态;然后在另一主机上启动本程序并选择client选项,向服务端发出连接请求;服务端收到连接请求后,自动调用onaccept()函数,根据客户端的请求顺序向其发出相应信息;客户端接收到服务端发出的信息后,在屏幕上显示一个提示框,按下“确认”按钮后,客户端将此信息发回服务端;服务端收到客户端发回的信息后,处理方式与客户端相同,就是这样实现了这个信息在两台计算机之间的来回传递。值得注意的是,在等待信息期间,这个程序还可以做其他的工作,比如可以选择菜单上的某个选项等,当然也可以加入其他的工作。

  运行本程序并选择作为服务端时最多可以同时接收五个客户的请求,因此可以同时运行本程序的六个实例,其中一个设置为服务端,另外五个设置为客户端。由于服务端实际上是用五个套接字分别与客户端通信,因此点对点的通信过程将会互不干扰地进行。

  6.源程序

  本文给出框架中被改动过的文件代码(即mysocket和childview的.h和.cpp文件的源代码)如下,这些程序均在vc ++ 6.0下编译通过,并在本文作者单位的网络环境上运行成功。

  mysocket.h文件:

  //派生套接字类

  class servesocket : public casyncsocket

  {public:

   char rx_buf[100];

   int serveno;

  public:

   servesocket();

   virtual ~servesocket();

  public:

   // classwizard generated virtual function overrides

   //{{afx_virtual(servesocket)

   public:

   virtual void onreceive(int nerrorcode);

   //}}afx_virtual

  }

  

  class mysocket : public casyncsocket

  {

  public:

   servesocket servesocket[5];

   int acceptno;

   int connectno;

   char rx_buf[100];

  public:

   mysocket();

   virtual ~mysocket();

  public:

   // classwizard generated virtual function overrides

   //{{afx_virtual(mysocket)

  public:

   virtual void onaccept(int nerrorcode);

   virtual void onreceive(int nerrorcode);

   //}}afx_virtual

  }

  

  mysocket.cpp文件中的有关部分:

  void servesocket::onreceive(int nerrorcode)

  {

   if(receive(rx_buf,100))

   {//重新发出收到的信息

   messagebeep(0);

   afxmessagebox(rx_buf);

   send(rx_buf,10);

   }

   else

   {//接收错误

   afxmessagebox("receive failed",14);

   return;

   }

   casyncsocket::onreceive(nerrorcode);

  }

  

  void mysocket::onaccept(int nerrorcode)

  {

   if(acceptno>4) return;

   if(!accept(servesocket[acceptno]))

   {//接收请求失败

   afxmessagebox("accept fail!",12);

   }

   else

   {//接收请求成功

   servesocket[acceptno].serveno=acceptno;

   switch(acceptno)

   {//根据接收次序,向客户端发出信息

   case 0:

   {servesocket[acceptno].send("message 0",10);break;}

   case 1:

   {servesocket[acceptno].send("message 1",10);break;}

   case 2:

   {servesocket[acceptno].send("message 2",10);break;}

   case 3:

   {servesocket[acceptno].send("message 3",10);break;}

   case 4:

   {servesocket[acceptno].send("message 4",10);break;}

   default:

   break;

   }

  // afxmessagebox("accept client!",14);

   acceptno++;

   }

   casyncsocket::onaccept(nerrorcode);

  }

  

  void mysocket::onreceive(int nerrorcode)

  {

   if(receive(rx_buf,100))

   {//将收到的信息重新发出

   messagebeep(0);

   afxmessagebox(rx_buf);

   send(rx_buf,10);

   }

   else

   {//接收错误

   afxmessagebox("receive failed",14);

   return;

   }

   casyncsocket::onreceive(nerrorcode);

  }

  

  3.childview.h文件中的有关部分

  class cchildview : public cwnd

  {

  ...public: mysocket socket_id;

   //定义套接字类...protected:

   //{{afx_msg(cchildview)}

   afx_msg void onpaint();

   afx_msg void onclient();

   afx_msg void onserver();

   //}}afx_msg declare_message_map()

  }

  

  4.childview.cpp文件中的有关部分

  begin_message_map(cchildview,cwnd )

   //{{afx_msg_map(cchildview) on_wm_paint()

   on_command(id_client, onclient)

   //菜单项id_client将程序设置为客户端 on_command(id_server, onserver)

   //菜单项id_client将程序设置为服务端 //}}afx_msg_map

  end_message_map()

  

  void cchildview::onclient()

  {

   cclientdc dc(this);

   //creat a socket

   socket_id.create();

   dc.textout(200,100,"connect",7);

   if(socket_id.connect("192.0.0.0",2000))

   //服务端主机ip地址和端口号

   dc.textout(200,120,"connect fail!",13);

   else

   dc.textout(200,120,"connect successful!",18);

  }

  

  void cchildview::onserver()

  {

   cclientdc dc(this);

   //创建已定义的套接字

   socket_id.create(2000);

   //为其分配一个端口(2000)

   //socket_id.bind(2000,"192.0.0.0");

   //端口号和服务端主机ip地址。不同的主机此地址不同。

   //开始监听

   dc.textout(200,100,"listen",6);

   socket_id.listen();

  }

  (作者地址:大连市中山区小龙街1号224大连海军舰艇学院 116018 收稿日期:1999.01.29)




上一篇:将Socket应用程序从Unix向Windows移植中应注意的几点问题 C+/VC  
下一篇:socket编程原理 C+/VC

浏览模式 : 显示全部 | 评论 : 0 | 排序 | 浏览 : 1544

我要发表文章
回复标题:  
    Email :
* 请输入验证码
 
统计数据
文章数量 : 300300
评论次数 : 460
访问次数 : 19303613
在线人数 : 2100

附近文章
  • 直接控制24位位图的象素(...
  • 如何制作DialogBar C+/VC
  • 网络程序设计 Sockets C...
  • 用Socket和MSHTML对象模型...
  • 将Socket应用程序从Unix向...
  • socket编程原理 C+/VC
  • Winsock网络通信 C+/VC
  • 用Winsock完成了话音的一...
  • pre-emptive multithread...
  • VC下的CSmtp类,带验证,BA...
热门文章
  • 如...
  • Socket编程中select()的妙...
  • 如何在DLL中创建窗体(对话...
  • 重载赋值运算符 C+/VC
  • 展现TRACE之威力 C+/VC
  • ·用豪杰大眼睛制作照片v...
  • 一個簡單的錄音放音程序 ...
  • 用Socket接口实现网络异步...
  • MFC动态创建控件的消息处...
  • 实现服务器端的多线程SOC...
最新文章
  • 09/北京代办国内外文凭Q...
  • 09/北京代办国内外文凭Q...
  • 09/北京代办国内外文凭Q...
  • 股票技术不准了
  • 2009年元旦放假安排
最近评论
  • xueshanfh
  • 匿名
  • 匿名
  • 匿名
  • 匿名
  • 匿名Martha Jack
  • 匿名
  • Tom Moddy
  • 匿名Jimmy Adams
  • 匿名
 
 

Copyright (C) 一算子网 2006-2008, All Rights Reserved 京ICP备06020154号
服务QQ: 有问题请留言 留言邮箱pinhu530@sohu.com