• Linux 14:HTTP协议与web服务器



    1. 浏览器与服务器通信过程

    1.1 建立连接

    浏览器与web服务器在应用层通信使用的是HTTP协议,而HTTP协议在传输层使用的是TCP协议。那么浏览器需要和web服务器三次握手建立连接后,才可以发送HTTP请求报文,服务器收到请求报文后,向浏览器回复HTTP应答报文。

    1.2 使用端口

    对于端口来讲,使用HTTP协议的程序一般默认使用80端口

    1.3 长连接与短连接

    浏览器服务器建立连接后,如果两次以上的请求复用同一个TCP连接,则称之为长连接。如果浏览器发送一次请求报文,服务器回复一次应答就断开连接,下次交互再重新进行三次握手建立连接,那么就被称作短连接。

    使用长连接更好,可以减少网络中的同步报文,也使得服务器的响应速度变快

    1.4 常见的 web 服务器

    ◼ Apache: 简单、速度快、性能稳定,并可做代理服务器使用

    ◼ IIS(Internet Information Server):安全性、强大、灵活

    ◼ Nginx:小巧而高效,可以做高效的负载均衡反向代理

    ◼ Tomcat:技术先进、性能稳定、免费

    1.5 服务器与浏览器通信图解

    2. HTTP请求

    2.1 HTTP请求的部分内容

    GET http://www.baidu.com/index.html HTTP/1.0
    User-Agent:Wget/1.12(linux-gnu)
    Host:www.baidu.com
    Connection:close

    图解
    在这里插入图片描述

    2.2 HTTP应答状态

    2.2.1 HTTP应答部分内容

    Http/1.0 200 OK
    Server:BWS/1.0
    Content-Lnegth:8024
    Content-Type:text/html;charset=gbk
    Set-Cookie:BAIDUID=A5B6C72D68CF639CE8896FD79A03FBDB:FG=1;expires=Wed,04-Jul-42 00:10:47 GMT;path=/;domain=.baidu.com
    Via:1.0 localhost(squid/3.0 STABLE18)

    图解
    在这里插入图片描述

    3. HTTP代码

    3.1 代码示例1:发送ok

    代码示例1

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<string.h>
      4 #include<unistd.h>
      5 #include<sys/socket.h>
      6 #include<arpa/inet.h>
      7 #include<netinet/in.h>
      8 #include<pthread.h>
      9 #include<fcntl.h>
     10 
     11 int socket_init();
     12 void *work_thread(void*arg);
     13 int main()
     14 {
     15     int sockfd=socket_init();
     16     if(sockfd==-1)
     17     {
     18         exit(1);
     19     }
     20     while(1)
     21     {
     22         struct sockaddr_in caddr;
     23         int len=sizeof(caddr);
     24         int c=accept(sockfd,(struct sockaddr*)&caddr,&len);
     25         if(c<0)
     26         {
     27             continue;
     28         }
     29         pthread_t id;
     30         pthread_create(&id,NULL,work_thread,(void*)c);
     31     }
     32 }
     33 
     34 int send_http(int c,char*name)
     35 {
     36     if(name==NULL||c<=0)
     37     {
     38         return -1;
     39     }
     40     char http_head[512]={"HTTP/1.1 200 OK\r\n"};
     41     strcat(http_head,"Server:myhttp\r\n");
     42     strcat(http_head,"Content-Length:2\r\n");
     43     strcat(http_head,"\r\n");
     44     strcat(http_head,"ok");
     45 
     46     send(c,http_head,strlen(http_head),0);
     47 }
     48 
     49 void* work_thread(void* arg)
     50 {
     51     int c=(int)arg;
     52     while(1)
     53     {
     54         char buff[1024]={0};
     55         int num=recv(c,buff,1023,0);
     56         if(num<=0)
     57         {
     58             break;
     59         }
     60         printf("recv:\n%s\n",buff);
     61         //解析报文,获得请求资源名称,组装应答报文发送数据
     62         send_http(c,"filename");//测试
     63         break;
     64     }
     65     close(c);
     66 }
     67 
     68 int socket_init()
     69 {
     70     int sockfd=socket(AF_INET,SOCK_STREAM,0);
     71     if(sockfd==-1)
     72     {
     73         return -1;
     74     }
     75 
     76     struct sockaddr_in saddr;
     77     memset(&saddr,0,sizeof(saddr));
     78     saddr.sin_family=AF_INET;
     79     saddr.sin_port=htons(80);//root
     80     saddr.sin_addr.s_addr=inet_addr("0.0.0.0");
     81 
     82     int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
     83     if(res==-1)
     84     {
     85         printf("bind 80 err\n");
     86         return -1;
     87     }
     88     res=listen(sockfd,5);
     89     if(res==-1)
     90     {
     91         return -1;
     92     }
     93     return sockfd;
     94 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    运行结果
    在这里插入图片描述

    ifconfig命令可以查看ip地址

    在这里插入图片描述

    3.2 代码示例1:发送ok

    代码示例2

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<string.h>
      4 #include<unistd.h>
      5 #include<sys/socket.h>
      6 #include<arpa/inet.h>
      7 #include<netinet/in.h>
      8 #include<pthread.h>
      9 #include<fcntl.h>
     10 #include<signal.h>
     11 
     12 #define PATH "/home/maria/c215/20220806/web"
     13 int socket_init();
     14 
     15 void *work_thread(void*arg);
     16 
     17 void sig_fun(int sig)
     18 {
     19     printf("浏览器异常关闭\n");
     20 }
     21 
     22 int main()
     23 {
     24     signal(SIGPIPE,sig_fun);
     25     int sockfd=socket_init();
     26     if(sockfd==-1)
     27     {
     28         exit(1);
     29     }
     30     while(1)
     31     {
     32         struct sockaddr_in caddr;
     33         int len=sizeof(caddr);
     34         int c=accept(sockfd,(struct sockaddr*)&caddr,&len);
     35         if(c<0)
     36         {
     37             continue;
     38         }
     39         pthread_t id;
     40         pthread_create(&id,NULL,work_thread,(void*)c);
     41     }
     42 }
     43 
     44 void send_http_head(int c,int filesize)
     45 {
     46 
     47     char http_head[512]={"HTTP/1.1 200 OK\r\n"};
     48     strcat(http_head,"Server:myhttp\r\n");
     49     sprintf(http_head+strlen(http_head),"Content-Length:%d\r\n",filesize);
     50     //strcat(http_head,"Content-Length:2\r\n");
     51     strcat(http_head,"\r\n");
     52     //strcat(http_head,"ok");
     53 
     54     send(c,http_head,strlen(http_head),0);
     55 }
     56 
     57 int open_file(char*filename,int*psize)
     58 {
     59     char path[128]={PATH};
     60     if(strcmp(filename,"/")==0)
     61     {
     62         strcat(path,"/index.html");
     63     }
     64     else
     65     {
     66         strcat(path,filename);
     67     }
     68     int fd=open(path,O_RDONLY);
     69     if(fd==-1)//文件不存在
     70     {
     71         *psize=0;
     72         return -1;
     73     }
     74 
     75     *psize=lseek(fd,0,SEEK_END);//文件大小
     76     lseek(fd,0,SEEK_SET);
     77     return fd;
     78 }
     79 int send_http(int c,char*name)
     80 {
     81     if(name==NULL||c<0)
     82     {
     83         return -1;
     84     }
     85     int filesize=0;
     86     int fd=open_file(name,&filesize);
     87     if(fd==-1)
     88     {
     89         send(c,"404",3,0);
     90         return -1;
     91     }
     92     send_http_head(c,filesize);//发送报头
     93     char data[1024]={0};
     94     int num=0;
     95     while((num=read(fd,data,1024))>0)
     96     {
     97         send(c,data,num,0);
     98     }
     99     close(fd);
    100 }
    101 
    102 char* get_name(char buff[])
    103 {
    104     if(buff==NULL)
    105     {
    106         return NULL;
    107     }
    108 
    109     char*ptr=NULL;
    110     char*s=strtok_r(buff," ",&ptr);
    111     if(strcmp(s,"GET")!=0)
    112     {
    113         return NULL;
    114     }
    115 
    116     s=strtok_r(NULL," ",&ptr);
    117     return s;
    118 }
    119 
    120 void* work_thread(void* arg)
    121 {
    122     int c=(int)arg;
    123     while(1)
    124     {
    125         char buff[1024]={0};
    126         int num=recv(c,buff,1023,0);//接收浏览器发送过来的请求报文
    127         if(num<=0)
    128         {
    129             break;
    130         }
    131         printf("recv:\n%s\n",buff);
    132         //解析报文,获得请求资源名称,组装应答报文发送数据
    133         char*filename=get_name(buff);
    134         if(filename==NULL)
    135         {
    136             break;
    137         }
    138         int res=send_http(c,filename);//测试
    139         if(res==-1)
    140         {
    141             break;
    142         }
    143 
    144     }
    145     printf("close\n");
    146     close(c);
    147 }
    148 
    149 int socket_init()
    150 {
    151     int sockfd=socket(AF_INET,SOCK_STREAM,0);
    152     if(sockfd==-1)
    153     {
    154         return -1;
    155     }
    156 
    157     struct sockaddr_in saddr;
    158     memset(&saddr,0,sizeof(saddr));
    159     saddr.sin_family=AF_INET;
    160     saddr.sin_port=htons(80);//root
    161     saddr.sin_addr.s_addr=inet_addr("0.0.0.0");
    162 
    163     int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    164     if(res==-1)
    165     {
    166         printf("bind 80 err\n");
    167         return -1;
    168     }
    169     res=listen(sockfd,5);
    170     if(res==-1)
    171     {
    172         return -1;
    173     }
    174     return sockfd;
    175 }                          
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175

    运行结果
    在这里插入图片描述


  • 相关阅读:
    [BSidesCF 2019]Kookie 1 , cookie伪造
    谈谈讲清楚这件事的重要性
    【CSS】头部尾部固定中间滚动
    Python数据可视化案例
    关于用户 email 邮件地址是否允许有加号的问题
    【JavaEE精炼宝库】网络原理基础——UDP详解
    PostCSS通过px2rem插件和lib-flexible将px单位转换为rem(root em)单位实现大屏适配
    Swift数组copy-on-write特性实例
    JAVA中在普通Maven⼯程连接Redis
    css relative 和absolute布局
  • 原文地址:https://blog.csdn.net/qq_48580892/article/details/126226569