TCP与HTTP协议以及爬虫

一、TCP协议相关内容

(一)TCP头部标志

TCP头部包含多种标志位,各标志位功能明确,具体如下:

  • SYN:作为请求连接的标志物,用于发起TCP连接请求。
  • ACK:响应报文标志位,表明此报文为对之前收到的报文的响应。
  • PSH:携带数据标志位,通知接收方应从缓冲区读取数据。
  • FIN:请求断开连接标志位,用于主动请求终止TCP连接。
  • RST:复位标志位(重置),当出现错误或连接异常时,用于重置连接。
  • URG:紧急指针标志位,指示报文中存在需要优先处理的紧急数据。

同时,TCP首部结构包含20字节固定首部与长度可变的选项部分,固定首部涵盖源端口、目的端口、序号、确认号、窗口、偏移、检验和、紧急指针等字段,还包含上述标志位;选项部分长度可变,填充字段用于使首部长度符合要求。TCP报文段由TCP首部和TCP数据部分组成,在网络传输中,TCP报文段作为IP数据部分,加上IP首部后形成IP数据报进行传输。

(二)TCP核心机制

TCP协议通过一系列机制保障数据传输的安全可靠,并提升传输效率。

1. 确保数据安全可靠的机制
  • 三次握手与四次挥手:三次握手用于建立可靠的TCP连接,第一次握手由客户端发送SYN报文请求连接,第二次握手服务器端回复SYN+ACK报文响应,第三次握手客户端发送ACK报文确认,连接建立;四次挥手用于断开TCP连接,客户端先发送FIN报文请求断开,服务器端回复ACK报文确认,待服务器端数据发送完毕后发送FIN报文,客户端再回复ACK报文,连接断开。
  • 应答机制:TCP对每一包数据都会给出响应应答。发送数据时,序列号表示该包数据的起始编号;响应报文中的确认号是接收方收到的最后一个字节编号加1,以此确保数据有序接收。
  • 超时重传机制:当数据发送出去后,若在指定时间内未收到接收方的响应,TCP会认为数据丢失,进而对该数据进行重传,保证数据不丢失。
  • 滑动窗口机制:设置一段缓冲区,用于缓存TCP已发送但未收到响应、以及准备发送的数据,通过窗口的滑动来动态调整数据的发送节奏,提高数据传输的连续性和可靠性。
2. 提高传输效率的机制
  • 延迟应答:发送数据的同时等待应答,避免频繁发送单独的应答报文,减少网络开销。
  • 流量控制机制:结合TCP头部的窗口大小字段,接收方根据自身缓冲区的空闲情况,动态调整窗口大小并告知发送方,发送方据此调整发送速率,防止接收方因缓冲区溢出而丢失数据。
  • 捎带应答机制:ACK报文(应答报文)可能与应用层的数据同时发送,将应答信息附着在数据报文中,减少单独发送应答报文的次数,提升网络资源利用率。

二、HTTP协议相关内容

HTTP(超文本传输协议)是万维网(WWW)体系中客户端与服务器之间通信的核心应用层协议,其相关内容围绕万维网数据标记、通信方式、数据展示及自身协议特性展开。

(一)万维网核心要素

  • 数据标记 :万维网服务器后台通过URL(统一资源定位符)标记万维网数据,URL格式为<协议>://<主机>:<端口><路径>,可精准定位网络中的资源。
  • 通信方式:万维网客户端与服务器之间使用HTTP协议进行通信,HTTP基于传输层的TCP协议,默认端口为80,备用端口为8080。
  • 数据展示:万维网客户端通过HTML(超文本标记语言)展示请求到的数据,HTML能对文本、图片、链接等多种元素进行排版和描述,呈现丰富的网页内容。

(二)HTTP通信过程

HTTP通信需经历以下4个步骤,依赖TCP连接保障数据传输:

  1. 建立TCP连接:客户端向服务器发起TCP连接请求,通过三次握手建立可靠连接。
  2. 发送HTTP请求报文:TCP连接建立后,客户端向服务器发送HTTP请求报文,请求所需资源。
  3. 接收HTTP响应报文:服务器接收并处理请求后,向客户端发送HTTP响应报文,包含请求结果及相关数据。
  4. 断开TCP连接:客户端接收响应报文后,通过四次挥手断开与服务器的TCP连接。

(三)HTTP报文格式

HTTP报文分为请求报文和响应报文两类,均为面向文本的协议,报文字段由ASCII码串组成,字段长度不确定。

1. 请求报文
  • 请求行 :包含方法、URL、版本,方法指定对资源的操作,常见方法及意义如下表所示:

    方法(操作) 意义
    OPTION 请求一些选项的信息
    GET 请求读取由URL所标志的信息
    HEAD 请求读取由URL所标志的信息的首部
    POST 给服务器添加信息(例如,注释)
    PUT 在指明的URL下存储一个文档
    DELETE 删除指明的URL所标志的资源
    TRACE 用来进行环回测试的请求报文
    CONNECT 用于代理服务器
  • 首部行:由多个"首部字段名:值"组成,每个字段后接CRLF(回车换行),用于传递请求的附加信息,如客户端信息、请求内容类型等。

  • 实体主体:通常不用,仅在部分请求(如POST)中用于携带向服务器提交的数据。

2. 响应报文
  • 状态行 :包含版本、状态码、短语,状态码为三位数字,分为5大类共33种,不同类别代表不同响应状态:
    • 1xx:通知信息,如请求收到或正在处理。
    • 2xx:表示成功,如接受或知道请求。
    • 3xx:表示重定向,需进一步行动完成请求。
    • 4xx:表示客户差错,如请求语法错误或无法完成。
    • 5xx:表示服务器差错,如服务器失效无法完成请求。
      常见状态行示例:
    • HTTP/1.1 202 Accepted(接受)
    • HTTP/1.1 400 Bad Request(错误的请求)
    • HTTP/1.1 404 Not Found(找不到)
  • 首部行:与请求报文的首部行格式类似,由"首部字段名:值"组成,传递响应的附加信息,如服务器信息、响应内容长度等。
  • 实体主体:部分响应报文包含,用于携带服务器返回给客户端的数据,如网页的HTML内容、图片数据等。

代码训练

1、爬虫

cs 复制代码
#include "head.h"

int create_tcp_connect()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        perror("socket error");
        close(sockfd); 
        return -1;
    }

    struct sockaddr_in seraddr;
    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(80);
    seraddr.sin_addr.s_addr = inet_addr("117.34.49.212");

    int ret = connect(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));
    if(ret < 0)
    {
        perror("connect error");
        return -1;
    }
    return sockfd;
}

int send_http_request(int sockfd)
{
    const char *prqus = "GET / HTTP/1.1\r\n"
                  "Host: news.sohu.com\r\n"
                  "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/113.0\r\n"
                  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n"
                  "Accept-Language: en-US,en;q=0.5\r\n"
                  "Connection: close\r\n"     // keep_alive   close
                  "\r\n";

    ssize_t cnt = send(sockfd, prqus, strlen(prqus), 0);
    if(cnt < 0)
    {
        perror("send error");
        return -1;
    } 
    return 0;
}

int recv_http_response(int sockfd)
{
    char buff[1024] = {0};
    while(1)
    {
        ssize_t cnt = recv(sockfd, buff, sizeof(buff), 0);
        if(cnt < 0)
        {
            perror("recv error");
            return -1;
        }
        else if(cnt == 0)
        {
            printf("off\n");
            break;
        }

        write(1, buff, cnt);  
    }
    return 0;
}

int main(int argc, char const *argv[])
{
    int sockfd = create_tcp_connect();
    if(sockfd < 0)
    {
        return -1;
    }

    send_http_request(sockfd);

    recv_http_response(sockfd);

    close(sockfd);

    return 0;
}
相关推荐
礼拜天没时间.1 小时前
深入理解HTTPS:从概念到实战优化
网络协议·http·https
童先生1 小时前
我想把minio弄成https访问能行吗?
网络协议·http·https
binbinaijishu881 小时前
Python爬虫入门指南:从零开始的网络数据获取之旅
开发语言·爬虫·python·其他
励志五个月成为嵌入式糕手7 小时前
0825 http梳理作业
网络·网络协议·http
DebugKitty8 小时前
网络编程1-基本概念、函数接口
运维·服务器·网络·网络协议·socket·tcp
2501_921290449 小时前
嵌入式第三十六天(网络编程(TCP))
网络·网络协议·tcp/ip
LCS-31210 小时前
Python爬虫实战: 爬虫常用到的技术及方案详解
开发语言·爬虫·python
青草地溪水旁12 小时前
HTTP数据之旅:一个网络请求的完整冒险
网络·网络协议·http
2501_9277730713 小时前
Linux系统操作编程——http
网络·网络协议·http