muduo源码分析--数据在muduo中的旅程

        在实例化一个EvenLoop之后,就会有两个socketfd(这两个套接字分别归属于两个Channel中,一个是异步唤醒的wakeFd,一个timequeue初始化的fd)被添加到监听队列中
        数据发送的流程:
        数据的发送主要靠异步唤醒,当主IO线程接受到一个新的连接后,在TcpServer中实例化一个TcpConnection,然后这个新的连接被挂载到某个线程池(EventLoopThreapPool)中的某个EventLoop, 然后会掉用户的连接回调(就是得到新的连接后,用户想在这个连接上做的动作,这是用户自己定义的,主不过通过TcpServer注册,渗透到TcpConnection中执行,当然用户的这个程序可以有,可以没有,在这个函数用可以发送数据,可以接受数据,这是服务器和客户端之间的协议问题,这里假如连接后马上发送数据,也就是用户自己定的连接回调函数里有发送数据的函数调用,反映到TcpConnection中就是connectionCallback_)。在实例化新连接时,在主IO线程所属的EventLoop中调用runInLoop函数,runInloop函数需要知道要运行的函数是什么,接受新连接时,这个函数是connectEstablish,这个函数是Channel中定义的
        在connectEstablish函数中有继承来自用户层的连接建立后相应的函数处理,函数为connectionCallback。发送数据时,用户层调用send()相关的函数,到TcpConnection中最终都是调用的sendInLoop函数,在这个函数中,如果当前这个套接字没有正在写数据,并且TcpConnection中的输出缓冲outputBuffer中没有数据,那么就实处直接发送数据,看能发送多少数据,如果数据发送接收完了,那么调用queueInLoop函数将用户层中自己定义的数据发送结束后干什么的函数(这个函数就是writeCompleteCallback_,这里假设在用户自己定义的writeComplteCallback_函数中是继续发送数据),queueInLoop函数的首先将需要执行的函数(这里就是用户自己定义的writeCompleteCallback_函数)存放到函数响亮中,如果当前可以可以执行这个向量中的函数(标志位是callingPendFunctors_),那么就调用wakeup()异步唤醒。这次数据的发送结束。但是一部唤醒是为了让 poll返回,执行EventLoop中函数向量中的回调。那么当前注册的回调就是writeCompletCallback_。这个回调中仍旧是发送数据。也就是说,每次数据发送完,都会注册回调,然后唤醒线程,让poll返回来执行刚刚注册的回调。说明在数据发送接收后,不仅将这次事件办的稳妥,接下来继续做什么在函数sendInLoop中通过queueInLoop函数也注册进去了,queueInLoop不仅仅注册了用户的函数,还要通知线程马上去处理刚刚注册的函数。
            到此为止,一次数据的发送完成,但是要明白,这次数据是在套接字可以写并且输出缓冲没有数据的情况下,直接将所有数据发送完的情况下完成的,那么假如当前此套接字正在写,或者输出缓冲还有数据,或者写了一次没有将数据全部写入套接字,这样的话怎么办?
        如果当前套接字上不可写,或者输出缓冲还有数据,那么将数据拷贝到输出缓冲中,并且开始关注这个套接字上的POLLOUT事件。
        如果当前这个套接字可写,且输出缓冲没有数据,但是直接写并没有写完全部数据,那么将剩余的数据存放到输出缓冲,然后关注POLLOUT事件。那么套接字上的POLLOUT事件到达怎么处理呢?
        在handleWrite()函数中有关于当POLLOUT事件到达时怎么处理(写到合理,还记得当某个socketfd上有事件到达时,只是执行与这个套接字向关联的Channel上的handleEvent函数即可,在这个函数里会执行handleRead,hadleWrite handleClose函数),在handleWrite函数中,从输出缓冲中读取数据直接写到channel关联的socketfd上,如果写完了,将关闭这个socketfd上的可写事件,同时注册写完以后的操作,来自用户层的writeCompleteCallback_。
        上述部分是关于用户发送数据的部分!
        那么用户怎么读取数据呢?
    
        用户读取数据都是从这个TcpConnection中的inputbuffer中读取即可。
        当某个套接字上出现POLLIN事件,TcpConnection中调用handleRead函数,在handRead函数中调用Buffer类中的readFd函数,这个函数负责将该套接字上的数据读到TcpConnection中的inputbuffer里。如果读取有数据,在handleRead函数中调用用户层的回调messageCallback_,用户层的这个回调是和inputBuffer打交道的!
        

       

你可能感兴趣的:(C++,线程,服务器,网络编程)