如何写一个Web服务器

如何写一个Web服务器,第1张

针对web服务器:首先你要去了解HTTP协议,web server说到底就是一个遵循Http协议的应用程序。可以先写一个简单的,然后去关注一些high performance相关的, i/o 复用(epoll), event loop, non-blocking, C10k问题,tcp调优(tcp_cork, tcp_nodelay...),高级I/O function(e.g. sendfile, writev, readv, mmap, splice, tee...), 常用的服务端架构(推荐陈硕的Muduo C++那本书,不是让你看muduo, 而是他讲的一些思想、做法和框)

这一次我们来分析下 muduo 中 Buffer 的作用,我们知道,当我们客户端向服务器发送数据时候,服务器就会读取我们发送的数据,然后进行一系列处理,然后再发送到其他地方,在这里我们想象一下最简单的 EchoServer 服务器,客户端建立一个连接,以后服务器和客户端之间的通信都是通过这个 connfd 发送和接受数据,于是每一个 connfd 都应该有一个自己 buffer ,当我们发送数据太快,服务器发送的太慢,则服务器会将待发送的数据这个 buffer 中,所以这就是这个类的作用。我们先看下 buffer 的结构是什么:

我们这里主要针对 connfd 这个对应的 channel 进行分析,首先上图是 buffer 的初始状态,前面 8 个字节中表示该 buffer 的大小,初始大小为 1024 。当客户端发送数据给服务器,同时若服务器接受缓慢,则会向 buffer 中开始写数据,则 writerIndex_ 会向右移动,假如此时移动到如下形式:

则此时缓冲区可以读的数据为 writerIndex_ - readerIndex_ ,可以写的数据为 buffer_.size() - writerIndex_ 。这时候当服务器有多余资源进行读操作,就可以去缓冲区读数据了,假如这时候的状态为如下:

这就是常见的几个状态,下面我们去看几个重点的函数

以上是基本的操作,下面的2个函数很重要,一个是向 connfd 写数据,一个是读数据,对于一个 TcpConnection 而言,当有数据来的时候,回去调用 handleRead 回调函数。我们知道 muduo 设置的每次读取的大小为 65536 字节,当缓冲区可写的数据大小大于 65536 ,就会直接将读到的数据写入到缓冲区中,但当缓冲区的可写数据大小小于 65536 的时候,就会将剩余数据先写到一个额外的空间

这里巧妙的使用了一个 readv 函数,可以通过按照大小自动写到不同的地方。其中当 extrabuf 也写了数据,就会调用 append 函数。

注意到有一个 makeSpace 函数,其中有一个注意点,比如当如下这种状态的时候:

此时 readerIndex_ 前面有一部分其实已经被读完了,是空的数据,所以 makeSpace 函数考虑了这一点,采用内存重组的方式,将 readerIndex_ 向前移动到 kCheapPrepend 处,然后就可以让空余的内存挨在一起

当向 connfd 发送数据的时候就比较简单了,直接将可读的数据发送给出去就行


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/404859.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-21
下一篇2023-05-21

发表评论

登录后才能评论

评论列表(0条)

    保存