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 }

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

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 }                          

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值