ARTSPConnection::postReceiveReponseEvent启动发送请求循环

  下面贴出安卓N版本ARTSPConnection是如何启动向服务端发送请求,接收服务端的响应这样一个循环的:
  

==>
void ARTSPConnection::postReceiveReponseEvent() {
    //mReceiveResponseEventPending条件变量一旦postReceiveReponseEvent被调用就设置为true,知道整个循环调用达到末端该mReceiveResponseEventPending才会被设置为false,这样保证一次只存在一个这样的循环处理
    if (mReceiveResponseEventPending) {
        return;
    }

    //新建一个消息msg,消息名为kWhatReceiveResponse,消息的处理者为this,也即ARTSPConnection
    //则该消息的处理发生在ARTSPConnection::onMessageReceived的case kWhatReceiveResponse处理分支
    sp<AMessage> msg = new AMessage(kWhatReceiveResponse, this);
    msg->post();

    //将mReceiveResponseEventPending变量设置为true,表示当前这样的一个循环正在进行中,不能再产生一次这样的循环。
    mReceiveResponseEventPending = true;
}

==>
void ARTSPConnection::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatConnect:
            onConnect(msg);
            break;

        case kWhatDisconnect:
            onDisconnect(msg);
            break;

        case kWhatCompleteConnection:
            onCompleteConnection(msg);
            break;

        case kWhatSendRequest:
            onSendRequest(msg);
            break;

        case kWhatReceiveResponse:
            //调用onReceiveResponse()函数对消息名为kWhatReceiveResponse的消息进行处理
            onReceiveResponse();
            break;

        case kWhatObserveBinaryData:
        {
            CHECK(msg->findMessage("reply", &mObserveBinaryMessage));
            break;
        }

        default:
            TRESPASS();
            break;
    }
}

==>
void ARTSPConnection::onReceiveResponse() {
    //这样的一次循环调用接近到了末端,mReceiveResponseEventPending设置为false,表示可以再进行一次这样的循环调用了
    mReceiveResponseEventPending = false;

    if (mState != CONNECTED) {
        return;
    }

    //创建一个timeval类型的时间结构体变量
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = kSelectTimeoutUs;

    //创建一个套接字描述符集合rs
    //并将该套接字描述符集合内存清零
    fd_set rs;
    FD_ZERO(&rs);
    //将之前创建的套接字描述符mSocket添加到该套接字描述符集合中
    FD_SET(mSocket, &rs);

    //调用select函数检查套接字描述符集合rs里添加的套接字的状态,
    //即查询它的可读性、可写性及错误状态信息
    //在这里查询可读性传入了 &rs,其他两个查询可写性及错误状态信息都是传入的NULL
    //说明在这里调用者只检查套接字描述符集合rs里套接字的可读性
    int res = select(mSocket + 1, &rs, NULL, NULL, &tv);

    if (res == 1) {
        //刚才只通过FD_SET(mSocket, &rs)向套接字描述符集合rs里添加了一个我们创建的套接字描述符mSocket
        //所以select函数的返回值res为1说明,套接字描述符mSocket描述的套接口具有可读性
        //调用MakeSocketBlocking(mSocket, true)函数阻塞该套接口,因为接下来需要从该套接口获取从服务端回应的消息
        MakeSocketBlocking(mSocket, true);

        //真正的从套接口获取服务端回应的消息是在receiveRTSPReponse函数里完成
        //后续文章为大家介绍receiveRTSPReponse函数
        bool success = receiveRTSPReponse();

        //成功从该套接口获取到服务端回应的消息后调用MakeSocketBlocking(mSocket, false)函数将该套接口设置为非阻塞状态
        MakeSocketBlocking(mSocket, false);

        if (!success) {
            // Something horrible, irreparable has happened.
            flushPendingRequests();
            return;
        }
    }

    //调用postReceiveReponseEvent()函数再次开启这样一次处理,
    //如此就形成了一个循环
    postReceiveReponseEvent();
}

  小结:该循环的建立流程是:postReceiveReponseEvent ==> onReceiveResponse ==> postReceiveReponseEvent。这是一个设计技巧,是循环处理某些事务的机制,机制的原理就是形成一个循环调用圈。
  select函数的百科介绍:select(),确定一个或多个套接口的状态,本函数用于确定一个或多个套接口的状态,对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息,用fd_set结构来表示一组等待检查的套接口,在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select()返回满足条件的套接口的数目。
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值