• Http服务器实现文件上传与下载(二)


    一、引言

      欢迎大家接着看我的博客,如何大家有什么想法的话回复我哦,闲话不多聊了,接着上一讲的内容来说吧,在上一节中已经讲到了请求头字符串的解析,并且在解析中我我们已经获取了url。就是上节中提到的/doing。当浏览器发送了/doing请求后,这是的与服务器的连接并没有中断,原因无他,就是浏览器等待接受服务端发来的信息,然后他对信息进行解析并显示在浏览器界面上。在编写Http服务器时的C/S结构时,我只编写服务端server,客户端直接用现成的浏览器即可。

      当服务端找到浏览器需要的内容的时候,现在服务端就需要把内容发送给浏览器即可。但是在HTTP协议中,发送具体内容之前,服务端还是要发送一个响应头,之前浏览器发送的叫做请求头,那么服务端也要发送一个响应头告诉浏览器,说你的请求我接受或者拒接。拒绝的话之后就没有具体实体内容发送,否则再告诉浏览器说你请求的内容的格式是html或者text,或者是音频等二进制文件等,并且告诉浏览器你请求内容的大小(这个非常重要)。当响应头发送完毕后,如果是同意浏览器的请求的话,那么接着发送具体的内容即可,接着关闭这个链接。

    二、HTTP协议

      现在我们来看一下这个响应头的一个例子,还是只说明一些我们现在需要知道的,其他内容读者可以自己去查找相关的内容。

    1 HTTP/1.1 200 OK
    2 Server:(Unix)
    3 Content-type:application/octet-stream
    4 Content-length:65144369
    5 Connection:Keep-Alive

      在这个例子中的响应头我们可以看到:

      1)在第一行就告诉浏览器http协议的版本是1.1,状态码是200,意思是OK,就是说你的请求我同意了。

      2)在第二行就是告知浏览器我服务器的名字。

      3)在第三行就是你请求的内容的格式是applicaiton/octet-stream,理解为二进制流即可。

      4)在第四行说明你请求内容的大小,单位是字节。

      5)第五行告诉浏览器是Keep-Alive连接方式。

      在这个协议头发送给浏览器时,还是每行结尾都有一个回车换行 。最后还是需要一个空行代表本响应头结束。还有一些协议内容到用用到时再讲,现在提出这几项即可。当这个协议头发送给浏览器后,浏览器对其解析。然后等待真正的请求内容。当服务端把浏览器的请求的具体内容发送完毕就关闭这个连接。

      讲到这里基本一个请求响应结束了。那在这里提一下如何处理大并发呢。其实在HTTP请求中,在每个URL请求中服务器并不关心一些请求是否来着同个浏览器,服务器做的只是有请求来临就对其连接发送数据,然后关闭数据。尽管可能来着同一客户端上的请求有数据上的关系,但是服务端只是在发送数据而已。所以对于同一个浏览器发送的多个请求和不同浏览器或者不同主机发送来的请求的对待都是一样的。就是每个请求都是独立的,并不关心这个逻辑关系。

      在这一篇中的主要内容也就讲完了,好像看起来比较短哦,哈哈。。。。。那么在讲一些细节上的内容吧。

      现在大并发的服务器linux中,主要在有线程,进程,select,poll,epoll的方式。这些方式在各个博客上都是有的,所以我并不想在解释一下,读者可以自己查询其中的不同之处。而本文开发的HTTP服务器采用线程的方式进行。主要是当一个请求来到时,就创建一个线程来处理。采用的linux下POSIX标准pthtread线程。如果其他读者可以采用其他的几种方式来处理。或者自己写个线程池来取代每次一个请求来创建一个线程。主要对其包裹在一个命名空间为MultiThread的线程Thread类中,接着是一些代码段:

    头文件(include/thread.h):

     1 /*
     2  * include/thread.h
     3  */
     4 
     5 #ifndef THREAD_H_
     6 #define THREAD_H_
     7 #include<pthread.h>
     8 #include<iostream>
     9 namespace MultiThread {
    10 
    11 class Thread {
    12 public:
    13     Thread();
    14     ~Thread();
    15     static int create_thread(pthread_t &pid,void* (*pFunc)(void *),void *arg);
    16     int stop_thread();
    17 
    18 };
    19 
    20 } /* namespace MultiThread */
    21 
    22 #endif /* THREAD_H_ */

    cpp文件(src/thread.cpp)

     1 /**
     2 *
     3 *     src/thread.cpp
     4 **/
     5 #include "thread.h"
     6 namespace MultiThread {
     7 
     8 Thread::Thread() {
     9 }
    10 
    11 Thread::~Thread() {
    12 }
    13 
    14 int Thread::create_thread(pthread_t &pid,void* (*pFunc)(void *),void *arg) {
    15     int ret=pthread_create(&pid,NULL,pFunc,arg);
    16     if(ret==0)
    17         std::cout<<"create_thread() ...succeed"<<std::endl;
    18     else
    19         std::cout<<"create_thread() ...failed"<<std::endl;
    20     return ret;
    21 }
    22 
    23 int Thread::stop_thread() {
    24     return 0;
    25 }
    26 
    27 } /* namespace MultiThread */

     看到现在,大家一定发现stop_thread()为空,应为我到现在还没用这个函数。并且到现在只用到create_thread函数,之后如果用到,接着在之后的文章中提出吧。

    如果大家对HTTP服务器感兴趣的话,接着看《Http服务器实现文件上传与下载(三)》和我学习HTTP服务器编写吧。

  • 相关阅读:
    大话位运算
    Docker部署jar包
    linux系统备份mysql数据库
    关于Centos7 firewalld防火墙开放端口后仍不能访问ftp和nginx的问题解决
    MySql查询当天、本周、本月、本季度、本年的数据
    c#模拟线性回归
    监控服务器配置(五)-----Redis_exporter安装配置
    监控服务器配置(二)-----Grafana安装配置
    监控服务器配置(三)-----Node_exporter安装配置
    js网页唤起支付宝进行支付
  • 原文地址:https://www.cnblogs.com/liferecord/p/4842443.html
Copyright © 2020-2023  润新知