【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>

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曦樂~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值