linux网络http

文章目录

协议

协议是一种 “约定”. socket api的接口, 在读写数据时, 都是按 “字符串” 的方式来发送接收的. 如果我们要传输一些"结构化的数据" 怎么办呢

协议就要出现了。所谓协议就是大家都按照这个规定发送数据给服务器,服务器都按照这个规定发送数据给本地。

其实网络通信的本质就是发送请求和接收回应,也就是发送resquest,接收respond。

定义结构体发送信息到网络叫序列化,定义结构体从网络发到本地叫反序列化
序列化反序列化用工具 json xml

url

url,url就是网址。
在这里插入图片描述

  • 登录信息一般是不显示的,忽略的。
  • 服务器端口是不可以省略的,但是为什么随便打开一个网址,服务器端口号都没有显示出来。原因是服务器端口号和协议是强绑定的。http的端口号就是80,https的端口号就是443,不会变。
  • ?往后跟的是参数。参数是以key-value来传参的。互联网是有行为的,1是把服务器的数据拿下来,2是把自己的数据拿到服务器。参数是和互联网行为有关的概念。

urlencode和urldecode

有一些特殊字符,已经倍url当作特殊意义理解了,因此不能随意出现。如果参数中带了这些特殊字符,就会被转义。

比如加号+是特殊字符,搜索c++的时候参数的++会被转义成%2B%2B,
在这里插入图片描述

urldecode就是把%2B%2B变回++

http

http是超文本传输协议。
基本特征:
1.无链接
2.无状态
3.简单快速

关于无链接的解释:
http不是基于tcp之上的吗,为什么是无链接的?
http是应用层的,tcp是传输层的。http并不关心底层到底要干嘛。
也就是说tcp建立连接和http无关,http直接向对方发送http request即可。

关于无状态的解释:
http本身是无状态的,并不会记录任何用户信息,http只进行简单的响应和请求,但是我们发现现实中网站是会记录用户信息的,是cookie+session来记录的

关于简单快速的解释:
简单体现在http只会request和respond。快速体现在他底层使用的是tcp协议。

短链接进行文本传输 http/1.0
http/1.1 长链接

http构成

http主要有request和respond构成。它们的结构也很相像。
request
在这里插入图片描述
respond
在这里插入图片描述

服务器是如何读取request,客户端是如何读取respond的呢?(由于tcp是字节流传输,读取可能会出现错误)
在这里插入图片描述

抓包原理

抓包工具相当于一个代理。本来浏览器直接向网络发送request,现在先把request发送给抓包工具,fiddler再发给网络。
在这里插入图片描述

telnet命令行抓包

telnet连上网之后给服务器发送request,它会给你返回respond
在这里插入图片描述
发送请求GET / HTTP/1.1 这就是刚刚讲的请求行,然后没有请求报头,再输入多一个空行,没有请求正文。
相当于这样:
在这里插入图片描述
respond:

在这里插入图片描述
第一行是回应行
HTTP/1.1 200 OK
第二行到空行前是相应报头。
空行后面都是相应正文。
在这里插入图片描述

fiddler抓包

fiddler抓https的包更加直观一些。
request
在这里插入图片描述

respond
在这里插入图片描述

post和get的对比

POST通过正文传参, GET通过url传参。
GET还可以从服务器上拿资源下来。
POST在传参的时候比GET更私密一些。

啥是传参,输密码就是一种传参。

比如
在这里插入图片描述
账号密码就是参数。
抓包看到以post发送request的参数是在请求正文里面回显出来的。
在这里插入图片描述
如果以get发送参数就会在url上体现出来,比如百度搜索的时候,输入关键字搜索。
在这里插入图片描述
抓包看一下是否是get,果然是!
在这里插入图片描述

http方法

在这里插入图片描述

  • GET是从服务器上获取资源。资源可以是文本,可以是视频,可以是任何东西。GET也可以传参。像搜索关键字等数据。

  • POST通常用来上传数据给服务器。数据是指那种像输账号密码一样的东西,不是文件

  • PUT通常是用来上传资源给服务器。

http状态码

在这里插入图片描述
3xx可以实现重定向。
在这里插入图片描述
简单来说就是,我输入一个网址,这个网址可以带我去另一个网址。后面写最简单的http服务器会写一下重定向。

HTTP常见Header(报头)

  • Content-Type: 数据类型(text/html等),一般是respond有
  • Content-Length: Body的长度,respond和request都可能有
  • Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
  • User-Agent: 声明用户的操作系统和浏览器版本信息;
  • referer: 当前页面是从哪个页面跳转过来的;
  • location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;
  • Cookie: 用于在客户端存储少量信息. 通常用于**实现会话(session)**的功能;
User-Agent

用程序去访问服务器并获取资源的行为叫爬虫。
wget命令就可以爬。

比如用wget www.baidu.com
在这里插入图片描述
本地就多了这么一个百度的首页信息文件
在这里插入图片描述
爬虫有可能会把服务器搞崩,因此很多网站会有反爬机制。服务器怎么识别你是正常用户还是爬虫用户呢?就是通过报头里面的User-Agent来判定的。
在这里插入图片描述

Content-type

在这里插入图片描述
常见的媒体格式类型如下:

  • text/html : HTML格式
  • text/plain :纯文本格式
  • text/xml : XML格式
  • image/gif :gif图片格式
  • image/jpeg :jpg图片格式
  • image/png:png图片格式
cookie

http本身是无状态的,但是如果是无状态的会给用户很差的体验,每一次访问一个网站都要重新登陆。

在这里插入图片描述

session

cookie有可能被窃取,为了减缓这个问题。引入了session。可以用session来为cookie加密。session是放在服务器的一个文件。存放着你的个人信息。

过程:
client发送request,server接收后set一个sid,并创建一个session文件。保存个人信息,然后返回respond的时候set-cookie = sid。当用户下次再访问的时候,request会自动发送cookie过去,server根据cookie里面的sid来识别个人信息。

在这里插入图片描述
但这并没有完全解决问题,盗取cookie还是有可能能上网的。但是已经很安全了,因为即使被盗取了cookie,账号密码等个人信息它还是拿不到的。

最简单的http服务器

和之前的socket编程是一样的。我总结一个流程模板,往上套即可。

流程模板

在这里插入图片描述
重点是怎么编写respond。先贴代码:(这里写的是短链接,因此连接完直接就close(sock)了)

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string>
using namespace std;

class httpServer
{
  private:
    int lsock;
    int port;
  public:
    httpServer(int _port) :port(_port) {}

    ~httpServer(){close(lsock);}

    void httpServerInit()
    {
      lsock = socket(AF_INET, SOCK_STREAM, 0);

      struct sockaddr_in local;
      local.sin_family = AF_INET;
      local.sin_port = htons(port);
      local.sin_addr.s_addr = INADDR_ANY;
      socklen_t addrlen = sizeof local;
      if(bind(lsock, (struct sockaddr*)&local, addrlen) < 0)
      {
        cerr << "bind error" << endl;
        exit(2);
      }
      
      if(listen(lsock, 5) == -1)
      {
        cerr << "listen error" << endl;
        exit(3);
      }
    }

    void httpService(int sock)
    {
      char request[100];
      ssize_t s = recv(sock, request, sizeof request - 1, 0);
      if(s > 0)
      {
         cout << request << endl;
		
         string respond = "http/1.0 200 OK
";
		
         respond += "Content-type: text/html
";
         respond += "
";

         respond += "
                <!DOCTYPE html>
                <html>
                <head>
                <title>most simplfied network</title>
                </head>
                <body>
                <h1>my first network</h1>
                <p>2022.3.17.13:38</p>
                </body>
                </html>
                ";
         send(sock, respond.c_str(), respond.size(), 0);
      }
      close(sock);
    }


    void start()
    {
      while(1)
      {
        struct sockaddr_in peer;
        socklen_t addrlen = sizeof peer;
        int sock = accept(lsock, (struct sockaddr*)&peer, &addrlen);
        if(sock == -1)
        {
          cerr << "accept error" << endl;
          continue;
        }
        cout << "get a new link" << endl;
        if(fork() == 0)
        {
          close(lsock);
          httpService(sock);
          exit(0);
        }
        close(sock);
      }
    }

};

抓包结果

访问结果
用telnet访问:可以得到我们的respond
在这里插入图片描述
用网页访问:显示出来的就是响应正文的html
在这里插入图片描述

respond编写

模板可以对应一下代码,我这里讲一下respond

 string respond = "http/1.0 200 OK
";
		
respond += "Content-type: text/html
";
respond += "
";

respond += "
      <!DOCTYPE html>
      <html>
      <head>
      <title>most simplfied network</title>
      </head>
      <body>
      <h1>my first network</h1>
      <p>2022.3.17.13:38</p>
      </body>
      </html>
      ";

这一行是响应行,version + code + code描述

 string respond = "http/1.0 200 OK
";

这一行分别是响应报头和空行。

respond += "Content-type: text/html
";
respond += "
";

这是响应正文:这是html语法,代表的是网站的具体内容。
下面是一个可视化的 HTML 页面结构(只有< body >标签中的内容会显示在浏览器中):
在这里插入图片描述

 respond += "
                <!DOCTYPE html>
                <html>
                <head>
                <title>most simplfied network</title>
                </head>
                <body>
                <h1>my first network</h1>
                <p>2022.3.17.13:38</p>
                </body>
                </html>
                ";

重点讲响应报头
响应报头里面可以写上面讲的header.像Content-types基本是一定要有的。(注意:写这些响应报头的名字的时候,最好格式完全一致。

可以实现一下重定向,通过访问服务器的ip来百度首页。
需要修改的就是code和code描述。并在响应报头那里加上location: https://www.baidu.com
即可。

效果图就不放了。开了fiddler之后访问有可能会失败,因为安全问题可能不允许我访问。但是关闭fiddler之后是可以访问的。

用telnet抓一下respond:
在这里插入图片描述

http vs https

http的端口好是80,https的端口号是443.
htt是直接把数据交给传输层的tcp。https并不是这样的,而是先经过一层软件层叫SSL/TLS(这两个东西没什么区别,TLS是标准版,SSL不是标准版)**加密,**然后再把数据给传输层。
在这里插入图片描述

对称加密

在这里插入图片描述

用对称加密有一个问题,密钥也是数据,这个密钥怎么让对方知道,如果直接发密钥就相当于发一个没有加密的数据了,很危险。

但实际上,https大部分都是用对称加密的,那它是怎么保证传输密钥的时候的安全的呢?

在发送密钥的时候,使用不对称加密

不对称加密

不对称加密就是我用A密钥加密,你用B密钥解密(RSA,基于因式分解的加密解密算法)。
在这里插入图片描述
注:对称的称为密钥。非对称才有公钥私钥之分。


不对称加密对应了两种密钥,一种是公钥,一种是私钥。

通常情况下:
公钥是用来进行加密的,私钥是用来解密的。(只能是)

https对称密钥加密过程(重要)

在这里插入图片描述

其实简单来说,就是把对称加密的密钥再加密一次防止被盗取。

怎么加密呢?用非对称加密,先用服务器的公钥为自己的对称密钥加密,再发送给服务器,这样别人就窃取不了了。

服务器得到加密后的对称密钥,可以用自己的私钥来解开公钥的加密。因此双方都得到了对称的密钥。

证书(*)

本地会存放一些证书,可以win + R后输入certmgr.msc去看一下
在这里插入图片描述
这些证书可以防止客户端和服务端之间有中间人窃取信息。(具体细节有点难)


防止数据被中间篡改

有可能出现这种情况。
黑客通过更换公钥破解了客户端的信息,并且不断地获取客户端发送地信息。更有可能出现篡改数据的情况。
在这里插入图片描述
怎么防止黑客中间篡改数据呢?
我们知道有一种数据结构叫字符串哈希。它可以给一个文本生成对应的哈希值(这个值叫数据摘要)。如果主机发现数据摘要发生变化,那么就证明数据被篡改了

问题又来了,数据摘要也可能被篡改,因此数据摘要也要用密钥加密起来。加密的摘要被称为数据签名(指纹)
在这里插入图片描述
总结来说:知道用哈希来加密文本数据即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值