自从写完最初的版本之后,一直在反思lnux服务器的高性能模型和架构。在大二也算做过数十个web项目,但因为当时所做的是网站后端居多,对服务器的理解并不深入 ,项目完成之后无非是将项目挂在apache制定的目录之下,然后启动服务器就可以了。
真正写过一个比较粗糙的项目之后,发现了点端倪,浏览器作为前端解释器,当URL地址栏发送之后 ,便向服务器发送了一次socket链接,网址被域名解析系统解析成ip地址之后,遍组装成了socket,网页http服务器的端口一般是80,这样,一次socket链接便向服务器发出了。发送数据的格式遵循应用层的http协议,我用了一个小技巧从服务器端获取了前端URL。浏览器发送的字符流中,地址 是以/字符开始,以空格结尾,那么用strchr获取这两个字符的位置,然后就能组装成url字符串了。虽然这种方式 原始又粗糙,还容易出错,不过至少能起作用,权且是 第一版本的待修改的地方吧。
当服务器获取了socket链接,从获取到的字符流中获得url资源定位符后,便针对url,开始在服务器端寻找资源文件的位置,如果没有 找到,向浏览器返回包含404错误的socket字符流,如果找到,按照协议组装成数据流 后便发送到浏览器端,也就是accept返回的新的socket的文件描叙符。
我利用的办法是读取找到的文件的内容后,形成字符流,然后向新的socketfd发送过去,这种办法首先效率非常令人怀疑,而且只能针对字符流read和write,如果是视频文件或者图片,就失效。我查询到有sendfile函数可以直接将文件发送过去,这个等待第二个版本继续 升级修改。
我最初的打算是将这个github上的项目解析完全之后,在该项目的基础上进行修改和 升级,但因为时间和精力考虑,而且因为目前能力限制,这个目的需要 加以时日,继续不断 进行下去吧。
高性能的服务器编程用到了io复用以及多线程,io复用其实是与轮询有关,将socketfd设置 为非阻塞态,然后利用 select, poll, epoll提供的轮询机制,一旦有数据可用,进行相应处理 ,如果是socke连接请求,将新的socketfd加入轮询对队列后重新轮询,主线程只用来接受连接,如果是数据读写请求,重新开辟新的线程去处理,这样便将效率提升了上去。算是最初的模型和构思吧。