> 文章列表 > 【Linux】HTTP超文本传输协议

【Linux】HTTP超文本传输协议

【Linux】HTTP超文本传输协议

http主要用在浏览器和web服务器通信,是基于TCP协议的应用层无连接的传输协议。

HTTP与HTTPS

http是明文数据传输,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息。协议使用端口号:80。

https更加安全:数据加密、校验(防止被篡改),建立https网站需要申请ca证书(证明合法性,防止中间人攻击)。协议使用端口号:443

        加密方法:对称+非对称加密+证书+数字签名(对比防止证书被修改)

 对称加密(对加密和解密使用相同密钥的加密算法):RC4、DES、3DES、AES、ChaCha20 等

非对称加密(公钥加密,私钥解密): DH、DSA、RSA、ECC 等。

访问http的网站:

        会被提示不安全。

https的网站:

        有一个安全的锁。

​​


HTTP请求

请求头部:

浏览器给服务器发送

每一行结束都有一个\\r\\n;

头部与数据部分隔一行\\r\\n,空行表明头部结束了

 请求方法:

GET客户端向服务端请求资源,POST客户端向客户端提交数据(如:自己换头像)

其中:GET、HEAD、TRACE、OPTIONS是安全的。

 应答头部:

服务端给浏览器发

 HTTP状态码:

1XX信息,告诉服务器自己还有数据发送;

2XX成功,200 OK;

3XX重定向;

4XX客户端错误;

5XX服务器错误;


 写一个服务端让浏览器使用ip连接 

        这里当服务端接收到浏览器的请求后向其发送:“打印ok?“,但是这是不符合它的应答格式的,此时浏览器无法解析,将其应答直接显示出来

        并且接收信息发送后就关闭了,这种为短链接。

文件

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

 创建套接字:

int socket_init()
{int sockfd = socket(AF_INET,SOCK_STREAM,0);assert(sockfd!=-1);struct sockaddr_in saddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family=AF_INET;saddr.sin_port = htons(80);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));assert(res!=-1);res = listen(sockfd,5);assert(res!=-1);return sockfd;
}

主函数:

        服务器收到浏览器请求后返回一个"打印ok?"

int main()
{int sockfd=socket_init();assert(sockfd!=-1);while(1){struct sockaddr_in  caddr;int len = sizeof(caddr);int c = accept(sockfd,(struct sockaddr*)&caddr,&len);if(c<0)continue;char buff[1024] = {0};int n=recv(c,buff,1023,0);if(n<=0){close(c);continue;}printf("%s\\n",buff);send(c,"打印ok?",7,0);close(c);}
}

申请1024大小的数组必须用管理员权限运行(不然不会分配这么多空间):

服务端可以收到发送请求的浏览器、系统的型号等等

这些数据都存在接收(recv)的buff中。

GET请求资源:

浏览器指定文件路径,GET后面的与浏览器上输入的东西一样,即把请求送给服务器。


让服务器回复指定数据:

        由于请求报文可以得到浏览器申请的数据文件地址,我们可以获取它,然后回一个应答报文。

头文件:

因为要打开文件,所以要加上fcntl.h

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<fcntl.h>
//当前程序的位置
#define PATH "/home/stu/day21"

创建套接字:

int socket_init()
{int sockfd = socket(AF_INET,SOCK_STREAM,0);assert(sockfd!=-1);struct sockaddr_in saddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family=AF_INET;saddr.sin_port = htons(80);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));assert(res!=-1);res = listen(sockfd,5);assert(res!=-1);return sockfd;
}

获取文件名:

//获取文件名(Get后面的东西)
char * get_filename(char buff[])//报头存在buff中
{char*s = strtok(buff," ");//分割出请求方法if(s==NULL)return NULL;printf("请求方法:%s\\n",s);s = strtok(NULL," ");//分出文件名return s;
}

主函数:

recv,拼接应答报文

默认的主页为index html

int main()
{int sockfd=socket_init();assert(sockfd!=-1);while(1){
//接收数据struct sockaddr_in  caddr;int len = sizeof(caddr);int c = accept(sockfd,(struct sockaddr*)&caddr,&len);if(c<0)continue;
//存请求char buff[1024] = {0};int n=recv(c,buff,1023,0);if(n<=0){close(c);continue;}
//打印请求printf("%s\\n",buff);
//获取浏览器指定的文件名char* filename = get_filename(buff);if(filename==NULL){close(c);//解析不了,直接关闭continue;}
//拼接http应答报文//PATH是自己定义的宏表示当前文件位置,下面要将文件名加到当前路径后char path[236] = {PATH};if(strcmp(filename,"/")==0)//filename只有一个/表示没有指定文件{strcat(path,"/index.html");// "/home/stu/day21/index.html"}else{strcat(path,filename);}//获取文件大小int fd = open(path,O_RDONLY);if(fd==-1)//文件没打开{close(c);continue;}int size = lseek(fd,0,SRRK_END);   //大小等于文件头到文件末尾的位置     lseek(fd,0,SEEK_SET);//再把偏移量移到文件头char head[128] = {"HTTP/1.1 200 0K\\r\\n"};strcat(head,"Server: myhttp\\r\\n");
//将内容格式化输出到一个buff中sprintf(head+strlen(head),"Content-Length: %d\\r\\n",size);strcat(head,"\\r\\n");//空行//输出头部 printf("\\n%s",head);
//给客户端发送头部send(c,head,strlen(head),0);
//给客户端发送数据char data[1024]={0};int num = 0;while((num=read(fd,data,1024))>0)//读数据{send(c,data,num,0);//发送}close(fd);close(c);}
}

html文件   

        把这个文件放在浏览器申请的文件夹中,服务器可以把它发给浏览器。

<html><head><meta charset="utf8"><title>c2202的主页</title></head><body>欢迎</body>
</html>