• CASyncSocket类和CSocket类编程


    CASyncSocket类和CSocket类编程      
          简言之,CSOCKET是对SOCKET   API   的高级而又简单的包装,而CAsyncSocket的包装就相对低级,  
      要求程序员自己处理的细节多,但应用就更灵活,更接近API,

            CSocket派生于CAsyncSocket,支持同步操作。  
            CAsyncSocket封装Windows   Sockets   API  

             windows的socket默认是阻塞模式,CAsyncSocket是非阻塞模式,CSocket是非阻塞模式的阻塞socket.阻塞非阻塞可以通过ioctlsocket函数来设置。

       
       
        本文主要讲解以下内容  
        (1)CAsyncSocket类编程模式。  
        (2)CSocket类编程模式。  
        (3)CSocketFile类和CArchive类简介。  
        通过学习,可以掌握CAsyncSocket类和CSocket类的编程模式,了解CSocketFile类和  
      CArchive类。CAsyncSocket类逐个封装了Winsock函数,以前介绍过的Winsock函数在CAsyncSocket类  
      的成员函数中都可以找到它们对应的函数。一个CAsyncSocket对象就代表着一个Windows   Socket,  
      使用这个类进行网络编程,就要求程序员对网络通信和Socket编程模式有相当的了解,因为程序员  
      要自己编写程序处理阻塞、字节顺序以及Unicode与MBCS之间的转换等问题。  
        为使程序员可以更方便地编写Socket程序,MFC又给出了CSocket类。CSocket类是CAsyncSocket  
      类的派生类,它在继承了CAsyncSocket类的所有函数的同时提供了比CAsyncSocket类更高层的网络  
      编程接口。利用CSocket类和与之搭配的CSocketFile类以及CArchive类编写网络程序更加简单便利,  
      这主要是由于在CSocket类中提供了阻塞模式,因而可以利用CArchive进行同步操作。  
       
        提示:  
        在这里需要特别强调一下阻塞函数的概念,一个Socket可以处于“阻塞模式”或“非阻塞模式”,  
      当一个Socket处于“阻塞模式”时,它的阻塞函数(如send函数、recv函数之类的函数)直到其操  
      作完成后才会返回给程序控制权,而Socket的阻塞在此之前不能作其他操作。如果Socket处于“非  
      阻塞模式”(即异步模式),调用函数将会立即返回给程序控制权。  
       
        对于阻塞函数引起的错误,调用CAsyncSocket类的GetLastError成员函数时,将返回错误  
      WSAEWOULDBLOCK。而对于CSocket类,由于它有自己的阻塞管理,则不会出现该类错误代码,  
      CSocket类的许多成员函数都带有阻塞性质,但可以结合CArchive类处理。在Win32环境下,如果  
      要使用具有阻塞性质的Socket,应该将其放在单独的工作者线程中,充分利用多线程编程不干预其他  
      线程的便利。多线程编程的方法,可以使程序员充分利用CSocket类的阻塞管理方式,而不影响到用  
      户界面线程。  
        要在MFC中进行Socket编程,需要在应用程序类的Initlnstance中调用AfxSocketlnit初始化套  
      接字。如果使用AppWizard创建应用程序的基本框架时,选中了“WindowsSockets”复选框,那么将  
      自动添加初始化代码。  
       
       
      1   CAsyncSocket类编程模式  
       
        在用MFC进行Winsock编程时,使用CAsyncSocket类的优点为:可以轻松处理多个网络协议,  
      效率高,灵活性好;它的缺点则是需要程序员编写程序来处理诸如阻塞等情况,比较麻烦。  
       
        提示:  
        使用CAsyncSocket类和CSocket类编程,需要加载头文件afxsock.h。  
       
        以下为CAsyncSocket类的编程模式。  
        1)创建一个Socket  
        创建一个Socket分为两步,首先调用CAsyncSocket类的构造函数创建一个CAsyncSocket类的  
      对象;然后调用成员函数Create创建底层套接字。构造套接字时,对于服务器端的程序,需要用一  
      个众所周知的端口提供服务;而对于客户端程序,使用缺省的参数调用Create函数创建Socket即可。  
      以下是创建Socket的程序代码举例。  
      (1)服务器端程序:  
      CAsyncSocketServerSocket;  
      int   nPort=27;  
      ServerSocket.Create(nPort,SOCK_DGRAM);  
      以上程序在栈中创建了一个CAsyncSocket对象,并用调用该对象的Create函数创建了一个数据  
      报式套接字。  
      CAsyncSocket* pServer=newCAsyncSocket;  
      intnPort=27;  
      pServer->Create(nPort);  
      以上程序在堆中创建了一个CAsyncSocket对象,并用调用该对象的Create函数创建了一个字节  
      流式套接字,创建字节流式套接字的Create函数的第二个参数可省略。  
      (2)客户端程序;  
      CAsyncSocketClientSocket;  
      ClientSocket.Create();  
      以上程序在栈中创建了一个CAsyncSocket对象,并使用以缺省参数调用该对象的Create函数创  
      建了一个数据报式套接字。对于客户端程序的Socket采用Create函数的缺省调用,可以使套接字自  
      主地选择一个能够使用的端口。  
      为了进一步说明Create函数的用法,下面给出该函数的原型:  
      BOOLCreate(UINT nSocketPort=0,int nSocketType=SOCK_STREAM,longlEvent=FD_READ   |  
        FD_WRITE   |   FD_OOB   |   FD_ACCEPT   |   FD_CONNECT   |   FD_CLOSE,   LPCTSTR  
        lpszSocketAddress=NULL);  
      参数说明:  
      nSocketPort:为套接字指定的端口,缺省时将自动为套接字选择可用的端口。  
      nSocketType:套接字类型,默认为字节流方式,如果把该参数设为SOCK—DGRAM,将创建数  
      据报式套接字。  
      lEevent:该参数用于指定可以通知相关窗口的消息,缺省为列出的所有事件都将生成相应的消  
      息通知相关的窗口。  
      lpszSocketAddress:套接字的网络地址,缺省时为本机的网络地址。  
       
        提示:  
        MFC定义了一个内部的类CSocketWnd,   当调用Create函数创建一个套接字时,就会将该套接  
      字连接到一个窗口(CSoketWnd的对象),CAsyncSocket的DoCallBack函数为该窗口的回调函数。  
      这样,   当一个网络事件发生时,经过MFC的消息循环,DoCallBack函数会根据不同的事件调用相应  
      的消息处理函数。MFC将这些消息处理函数定义为虚函数,在编程时必须重载需要的消息处理函数。  
       
        2)客户端连接与服务端监听  
        对于客户端程序,需要调用Connect成员函数连接到服务器,如以下程序所示:  
      ClientSocket.Connect(addr,nPort);  
      参数说明:  
      addr:服务器地址,例如“202.12.15.1”或www.microsoft.com之类的网络地址。  
      nPort:服务器Socket端口号。  
      对于服务器端程序,需要调用Listen成员函数对Socket所在的端口进行监听,一旦收到连接请  
      求,则调用Accept成员函数开始接收,如以下程序所示:  
      ServerSocket.Listen();  
      ServerSocket.Accept(CAsyncSocket& rConnectedSocket);  
      Accept函数的参数为一个空的CAsyncSocket对象,即由CAsyncSocket的构造函数构造的还未调  
      用Create成员函数创建套接字的CAsyncSocket对象。  
       
        提示:  
        为了进一步说明Accept函数的用法,下面给出该函数的原型:  
      virtual   BOOL   Accept(CAsyncSocket& rConnectedSocket,SOCKADDR   lpSockAddr=NULL,int  
      lpSockAddrLen=NULL);  
      (1)调用其他的CasyncSocket成员函数进行通信管理。  
      (2)   网络通信结束后,对于在栈中创建的CAsyncSocket对象,如果对象超出定义的范围时将自  
      动调用析构函数释放相关资源;对于在堆中创建的CAsyncSocket,需要调用delete操作销毁对象符  
      释放相关资源。  
        2   CSOCket类编程模式  
       
        CSocket类是CAsyncSocket类的派生类,它们都是从CObject类继承下来的.CSocket类代表  
      了比CAsyncSocket类更高层次的网络接口抽象。CSocket可以和CSocketFile类、CArchive类一  
      起管理数据的接收和发送。  
      以下为CSocket类的编程模式:  
      (1)创建Socket  
      ●服务器端程序:  
      CSocketsockSrvr;  
      sockSrvr.Create(nPort);   //用指定端口创建套接字  
      ●客户端程序:  
      CSocketsockClient;  
      sockClient.Create();   //用缺省的端口创建套接字  
      (2)连接  
      ●服务器端程序:  
      sockSrvr.Listen();   服务器端程序对指定连接端口进行监听  
      CSockersockRecv;   //创建一个空的CSocket对象  
      sockSrvr.Accept(sockRecv);   //接受客户端的连接请求  
      ●客户端程序:  
      sockClient.Connect(strAddr,nPort);//连接指定地址的服务器(参数strAddr中指定)  
      (3)数据传输  
      ●服务器端程序:  
      CSocketFile file(&sockRecv);  
      //创建与CSocket类的对象相连接的CSoeketFile类对象  
      CArchive arin(&file,CArchive::load);  
      //创建与CSocketFile类的对象相连接的CArchive类对象,用于存储将要发送的数据  
      CArchive arout(&file,CArchive::load);  
      //创建与CSocketFile类的对象相连接的CArchive类对象,用于存储接收的数据  
      arin>>dwValue;   //发送数据dwValue  
      arout<<dwValue;   //接收数据dwValue  
      ●客户端程序:  
      CSocketFile file(&sockClient);  
      //创建与CSocket类的对象相连接的CSocketFile类对象  
      CArchive arin(&file,CArchive::load);  
      //创建与CSocketFile类的对象相连接的CArchive类对象,用于存储将要发送的数据  
      CArchive arout(&file,CArchive::load)  
      //创建与CSocketFile类的对象相连接的CArchive类对象,用于存储接收的数据  
      arin>>dwValue;   //发送数据dwValue  
      arout<<dwValue;   //接收数据dwValue  
      (4)   网络通信结束后,对于在栈中创建的CSocket对象、CArchive对象、CSocketFile对象,如  
      果对象超出定义的范围时将自动调用析构函数释放相关资源;对于在堆中创建的对象,需要调用delete  
      操作销毁对象符释放相关资源。  
       
        提示:  
        关于CArchive类和CSocketFile类的知识将在后面的小节中介绍,在这里只需要有个大致的了解  
      即可。  
       
        除了利用CSocketFile类的对象和CArchive类的对象辅助数据传输外,利用CSocket的成员函数  
      同样可以实现数据的网络传输。  
      下面为利用CSocket成员函数的编程模式:  
      (1)创建Socket  
      ●服务器端程序:  
      CSoeket soekSrvr;  
      sockSrvr.Create(nPort);   //用指定端口创建套接字  
      ●客户端程序:  
      CSocket sockClient;  
      sockClient.CreateO;   //用缺省的端口创建套接字  
      (2)连接  
      ●服务器端程序:  
      sockSrvr.Listen();   //服务器端程序对指定连接端口进行监听  
      CSocket sockRecv;"创建一个空的CSocket对象  
      sockSrvr.Accept(sockRecv);   //接受客户端的连接请求  
      ●客户端程序:  
      sockClient.Connect(strAddr,nPort)//连接指定地址的服务器(参数strAddr中指定)  
      (3)数据传输  
      ●服务器端程序:  
      sockRecv.SendTo(esSendText,csCounts,nPort,strAddr);  
      //调用SendTo成员函数将csSendText指向的缓冲区数据传送到参数strAddr所代表的  
      //网络地址。  
      ●客户端程序:  
      sockClient.RecieveFrom(csRecieveText,csCounts,strAddr,nPort);  
      //调用ReciveFrom成员函数将从strAddr所代表的网络主机传送来的数据保存在//csReciveText  
      指向的缓冲区中。  
      (4)通话结束处理  
      ●服务器端程序:  
      sockSrvr.Close();  
      sockRecv.Close();  
      ●客户端程序,  
      sockClient.C!ose();  
      此外,还要删除相应的CSocket对象,释放资源


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/carl2380/archive/2010/08/24/5833708.aspx

  • 相关阅读:
    设计模式:观察者模式
    设计模式:享元模式
    面试题:redis主从数据库不一致如何解决?
    面试题:Object obj = new Object()这句话在内存里占用了多少字节
    面试题:AtomicInteger和LongAdder区别
    @PrePersist 注解
    树莓派 zero w 添加微雪墨水屏 显示天气
    数据仓库项目中的数据建模和ETL日志体系
    TO B业务的发展
    Kylin、Druid、ClickHouse核心技术对比
  • 原文地址:https://www.cnblogs.com/carl2380/p/2093394.html
Copyright © 2020-2023  润新知