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

原创 2001年08月19日 15:37:00


用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接口实现网络异步通信

2001年08月19日 15:37:00 用Socket接口实现网络异步通信   马爱民   VC ++ 4.1以上版本的开发环境提供了Socket接口,可以方便地进行网络通信。本文是在一个应...
  • softart
  • softart
  • 2007年10月27日 08:03
  • 231

使用Java NIO实现异步的socket通信

最近在学习NIO与socket,发现了一组比较好的文章:http://blog.csdn.net/kongxx/article/details/7288896。这篇文章使用Selector来管理Ser...
  • zhouxinyubest
  • zhouxinyubest
  • 2014年03月01日 22:46
  • 1624

Socket异步通信概念及应用

本文是我在网上学习,感觉挺好的就转过来了,原文在http://mervyn807.blog.163.com/blog/static/45307259201001524659631/...
  • taogang1108
  • taogang1108
  • 2010年06月09日 17:02
  • 4510

C#:简单的Socket异步通信功能(客户端)

上一篇(http://www.rexcao.net/archives/159)讲了服务端使用Socket发送消息的方法,这一篇来解决一下客户端如何接收服务端消息的问题。 目标 1、异步接收...
  • jsjpanxiaoyu
  • jsjpanxiaoyu
  • 2016年10月28日 13:07
  • 2236

网络通信——socket(TCP/IP).Http,同步和异步的区别

1首先说下同步和异步的区别吧 同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 (比如 普通B/S模式) 异步:请求通过事件触发->服务器处理(这是...
  • u013424496
  • u013424496
  • 2016年06月24日 11:06
  • 4517

C#Socket同步异步通讯总结笔记

同步套接字通信Socket支持下的网上点对点的通信服务端实现监听连接,客户端实现发送连接请求,建立连接后进行发送和接收数据的功能服务器端建立一个socket,设置好本机的ip和监听的端口与socket...
  • kenkao
  • kenkao
  • 2010年03月25日 17:28
  • 11542

socket异步通信-非阻塞模式(异步非阻塞)

将一个socket 设置成阻塞模式和非阻塞模式,使用fcntl方法,即: 设置成非阻塞模式: 先用fcntl的F_GETFL获取flags,用F_SETFL设置flags|O_NONBLOCK; ...
  • le119126
  • le119126
  • 2014年07月07日 15:57
  • 1547

Socket同步通信与异步通信

Socket有同步阻塞方式和异步非阻塞方式两种使用,事实上同步和异步在我们编程的生涯中可能遇到了很多,而Socket也没什么特别。虽然同步好用,不费劲,但不能满足一些应用场合,其效率也很低。    也...
  • God_love
  • God_love
  • 2010年07月30日 08:50
  • 1885

Windows的异步通信机制概述

windows系统中在很多
  • bobopeng
  • bobopeng
  • 2014年06月01日 22:42
  • 1036

C#TCP Socket网络编程(异步通信方式)

一、Socket编程 Socket即为套接字,它其实是一个句柄,存在于内存中的一个标识符,作为网络通信的一个符号。 Socket类位于System.Net.Sockets命名空间,封装了与套接字编...
  • kevin_IoT
  • kevin_IoT
  • 2017年02月08日 12:34
  • 1000
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:用Socket接口实现网络异步通信
举报原因:
原因补充:

(最多只允许输入30个字)