C++ 非阻塞套接字的使用 (2)

继续话题——软件中的异步非阻塞通讯方式。

由于软件基于MFC开发,所以实现异步通讯时使用了CAsyncSocket类。

首先要了解CAsyncSocket异步机制,引用自

http://blog.csdn.net/tianhai110/article/details/2115270

由于CAsyncSocket采用的是异步非阻塞机制,所以你随时可以发包,也随时可能收到包。

发送、接收函数都是异步非阻塞的,顷刻就能完成,所以收发交错进行着。也正因为如此,仅调用

它们并不能保障发送或接收的完成。例如发送函数Send,调用它可能有3种结果:错误、部分完成、

全部完成。其中错误又分两种情况:一种是由各种网络问题导致的失败,你需要马上决定是放弃本次操作,

还是启用某种对策;另一种是“忙”,你实际上不用马上理睬。你需要调用GetLastError来判断是哪种情况,

GetLastError返回WSAEWOULDBLOCK,代表“忙”,为什么当你Send得到WSAEWOULDBLOCK却

不用理睬呢?因为CAsyncSocket会记得你的SendWSAEWOULDBLOCK了,待发送的数据会写入

CAsyncSocket内部的发送缓冲区,并会在不忙的时候自动调用OnSend,发送内部缓冲区里的数据。

同样,如果Send只完成了一部分,你也不需要理睬,尚未发送的数据同样会写入CAsyncSocket内部的

发送缓冲区,并在不“忙”的时候自动调用OnSend完成发送。

与OnSend协助Send完成工作一样,OnRecieve、OnConnect、OnAccept也会分别协助Recieve、

Connect、Accept完成工作。这一切都通过消息机制完成。

在你使用CAsyncSocket之前,必须调用AfxSocketInit初始化WinSock环境,而AfxSocketInit会

创建一个隐藏的CSocketWnd对象,由于这个对象由Cwnd派生,因此它能够接收Windows消息。一方面它

会接受各个CAsyncSocket的状态报告,另一方面它能捕捉系统发出的各种SOCKET事件。所以它能够成为

高层CAsyncSocket对象与WinSock底层之间的桥梁:例如某CAsyncSocket在Send时WSAEWOULDBLOCK了,

它就会发送一条消息给CSocketWnd作为报告,CSocketWnd会维护一个报告登记表,当它收到底层WinSock

发出的空闲消息时,就会检索报告登记表,然后直接调用报告者的OnSend函数。所以前文所说的CAsyncSocket

会自动调用OnXxx,实际上是不对的,真正的调用者是CSocketWnd——它是一个CWnd对象,运行在独立的线程中。

以上是CAsyncSocket的原理,而具体代码如下(接收端):

首先在头文件中声明继承自CAsyncSocket的类,并重写三个方法:

#include <afxsock.h>

class CMyAsyncSocket :
    public CAsyncSocket
{
public:
    CMyAsyncSocket(void);
    ~CMyAsyncSocket(void);

    virtual void OnClose(int nErrorCode);
    virtual void OnConnect(int nErrorCode);
    virtual void OnReceive(int nErrorCode);
};

在cpp文件中分别实现这三个方法:

void CMyAsyncSocket::OnClose(int nErrorCode)
{
    if ( 0 == nErrorCode)
    {
        Close();
    }
    CAsyncSocket::OnClose(nErrorCode);
}

void CMyAsyncSocket::OnConnect(int nErrorCode)
{
    if (0 == nErrorCode)
    {
        //TODO:建立连接后的动作
    }
    CAsyncSocket::OnConnect(nErrorCode);
}

void CMyAsyncSocket::OnReceive(int nErrorCode)
{
    if (0 == nErrorCode)
    {
        //TODO:接受后的处理
        char szRcv[513] = "";
        int nRcved = Receive(szRcv,15);
    }
    CAsyncSocket::OnReceive(nErrorCode);
}

接下来,在需要通信的文件中就可以调用这个类:

    CMyAsyncSocket m_pClientSocket; 

    AfxSocketInit();
    m_pClientSocket.Create();
    m_pClientSocket.Connect(_T("IP"),PORT);

在使用过程中有三个地方需要注意:

    1.使用前进行AfxSocketInit()初始化;

2.如果出现消息只能接受一次的现象,注意在Receive()后调用父类的OnReceive();

3.在一个方法中,Connect()函数后面不能出现其他代码(这个尚不清楚原因)。

时间: 2024-08-30 08:31:01

C++ 非阻塞套接字的使用 (2)的相关文章

C++ 非阻塞套接字的使用 (3)

异步非阻塞套接字避免了死循环的接收问题,但是软件用起来体验还是很差.究其原因,软件在指令的发送.接收上, 采取了一种不合理的方式:在指令的发送后,立刻调用接收函数,等待回令. 若是采用同步阻塞套接字,那么如果连接出现问题没有回令,那么软件进程会始终等待锁死,这样显然是不合理.于是 采用同步非阻塞的接收方式,timeout被设置为NULL.这时会出现发令与回令的错位问题.这是由于,相应回令没有及时到 达,而接收函数已经返回,第一条发令被当做无回令处理:而此时回令被堆积在了缓冲区,被第二条发令接收到

11 非阻塞套接字与IO多路复用(进阶)

1.非阻塞套接字 第一部分 基本IO模型 1.普通套接字实现的服务端的缺陷 一次只能服务一个客户端! 2.普通套接字实现的服务端的瓶颈!!! accept阻塞! 在没有新的套接字来之前,不能处理已经建立连接的套接字的请求. recv 阻塞! 在没有接受到客户端请求数据之前, 不能与其他客户端建立连接! 3.普通服务器的IO模型 第二部分 非阻塞套接字 1.非阻塞套接字与普通套接字的区别 >>> import socket >>> server = socket.sock

非阻塞套接字与IO多路复用

我们了解了socket之后已经知道,普通套接字实现的服务端的缺陷:一次只能服务一个客户端! 并且,为了使一个客户端能够不断收发消息,我们还要使用while循环来轮询,这极大地降低了我们的效率 accept阻塞! 在没有新的套接字来之前,不能处理已经建立连接的套接字的请求 recv 阻塞! 在没有接受到客户端请求数据之前,不能与其他客户端建立连接 可以用非阻塞接口来尝试解决这个问题! 阻塞IO模型 阻塞IO(blocking IO)的特点:就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被

非阻塞套接字实现并发处理

服务端 import socket server = socket.socket() server.setblocking(False) server.bind(('0.0.0.0',8080)) server.listen(1000) all_connection = []#所有连接的客户端,用集合比列表更快 while True: try: connection,remote_address = server.accept()#非阻塞对等连接套接字生成 connection.setblock

阻塞套接字返回EAGAIN

今天用NDK写了一个通信程序,发现阻塞SOKCET 读写的时候返回了EAGAIN.NDK下PERROR输出为Try Again.查了半天头文件 在网上找到了原因.在此纪录.网址为http://blog.csdn.net/cleanfield/article/details/41649985 2)socket设置SO_RCVTIMEO和SO_SNDTIMEO对read/write有什么影响?看man怎么说 SO_RCVTIMEO and SO_SNDTIMEO Specify the receiv

阻塞的套接字与非阻塞的套接字

阻塞模式 Windows套接字在阻塞和非阻塞两种模式下执行I/O操作.在阻塞模式下,在I/O操作完成前,执行的操作函数一直等候而不会立即返回,该 函数所在的线程会阻塞在这里.相反,在非阻塞模式下,套接字函数会立即返回,而不管I/O是否完成,该函数所在的线程会继续运行. 在阻塞模式的套接字上,调用任何一个Windows Sockets API都会耗费不确定的等待时间.图所示,在调用recv()函数时,发生在内核中等待数据和复制数据的过程. 当调用recv()函数时,系统首先查是否有准备好的数据.如

socket阻塞与非阻塞,同步与异步、I/O模型,select与poll、epoll比较

1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步/异步主要针对C端: 同步:      所谓同步,就是在c端发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:      异步的概念和同步相对.当c端一个异步过程调用发出后,调

基础入门_Python-网络编程.分分钟掌握阻塞/非阻塞/同步/异步IO模型?

概念梳理: 故事独白: 满满爱喝茶,废话不多说,开始煮开水. 出场人物: 满满, 普通水壶, 高级水壶(水开会响) 1. 满满把水壶放在火上, 站在那里等水开(同步阻塞) 满满觉得自己有点儿傻逼~ 2. 满满把水壶放在火上,去客厅看电视,时不时的去厨房瞅瞅水开木有(同步非阻塞) 满满觉得自己还是有点傻~,于是买了个高级水壶, 水开后会响~ 3. 满满把高级水壶放在火上, 站在那里等水开(异步阻塞) 满满想高级水壶水开会自己叫~为毛不去看个电视哪? 4. 满满把高级水壶放在火上, 去客厅看电视,

socket阻塞与非阻塞,同步与异步、I/O模型

socket阻塞与非阻塞,同步与异步 作者:huangguisu 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:同步:      所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:      异步的概念和同步相对