LINUX 入门 7

LINUX 入门 7

day10 20240506 耗时:59min

day11 20240507 耗时:106min

课程链接地址

第7章 http客户端请求

1 http项目介绍与Http协议讲解

先去看一遍教程 扫一遍,不用完全一行行读

ctrl+shift+I调出来网页调试台——network——img

过程

  1. client 浏览器建立与百度服务器的tcp连接(用DNS翻译成ip)
  2. 在tcp 连接socket上发送http协议请求request(连接IP地址端口)
  3. 百度server在tcp的socket连接上返回一个http协议相应response

在这里插入图片描述

头部字段名有好多好多好多

2 http项目,hostname转换ip

  1. struct hostent *host_entry = gethostbyname(hostname);

    它接受一个字符串类型的主机名作为参数,并返回相应主机的 IP 地址。

    这个函数使用了 gethostbyname 函数来获取指定主机名对应的 struct hostent 结构体。该结构体包含了与主机名相关联的信息,包括 IP 地址等。

    但需要注意的是,gethostbyname 函数在一些操作系统中已经被标记为过时(deprecated),推荐使用 getaddrinfo 函数来替代。如果你正在开发新项目或者进行更新,建议考虑使用更现代化的方法来获取主机名对应的 IP 地址。

// 1 不像上次DNS翻译太麻烦,直接用接口gethostbyname
char *host_to_ip(const char* hostname){
    struct hostent *host_entry = gethostbyname(hostname);

    // 点分十进制, 14.215.177.39--->unsigned int
    //  inet_ntoa: unsigned int-->char *    0x121212--->"18.18.18.18"
    if(host_entry) return  inet_ntoa((struct in_addr*)host_entry->h_addr_list); 
    return NULL;

}

3 http项目tcp socket链接

TCP连接必须先建立一个socket

  1. struct sockaddr_in 多年没变,接口pasca api很稳定,即使内核升级,应用没事

  2. 阻塞

    if socket阻塞,read()时,一旦socket里没数据,整个线程挂起等io数据来

    if 非阻塞,立马返回,线程不会挂起

    一般选非阻塞IO

    调用 fcntl(sockfd, F_SETFL, O_NONBLOCK) 的作用是将 sockfd 所代表的套接字文件描述符设置为非阻塞模式。这意味着在进行读写操作时,它不会阻塞等待结果返回,而是立即返回。

// 2 连接服务器
int http_create_socket(char *ip){
    // TCP连接必须先建立一个socket
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in sin = {0};
    sin.sin_family = AF_INET;
    sin.sin_port= htons(80);
    sin.sin_addr = inet_addr(ip); //ip变成域名反过来
    
	if (0 != connect(sockfd, (struct sockaddr*)&sin, sizeof(struct sockaddr_in))) {
		return -1;
	}
    fcntl(sockfd, F_SETFL, O_NONBLOCK); //阻塞非阻塞

	return sockfd;
}

4 http项目 send http请求

查pdf——客户端请求消息

1.\r\n 是两个特殊字符的组合,表示回车(Carriage Return)和换行(Line Feed),常用于文本文件中的换行符。它们在不同的操作系统中有不同的使用方式:

  • 在 Unix/Linux 系统中,通常使用 \n 作为换行符。
  • 在 Windows 系统中,通常使用 \r\n 作为换行符。
  • 在老式 Macintosh 系统中,通常使用 \r 作为换行符。

所以,当你需要跨平台编写代码时,在文本处理或网络传输中都建议使用 \r\n 作为换行符,这样可以保证在各种操作系统上正确解析和显示换行。

  1.     sprintf(buffer, 
        "GET %s %s\r\n
        HOST: %s\r\n,
        %s\r\n\
        \r\n",
        resource, HTTP_VERSION, 
        hostname,
        CONNETION_TYPE
        );
    
    
    • %s 是一个占位符,用于替代 resource、HTTP_VERSION、hostname 和 CONNECTION_TYPE 变量的值。

3 send(sockfd,buffer, strlen(buffer), 0);

  • sockfd 是已连接套接字的文件描述符。

  • buffer 是要发送的数据缓冲区。

  • strlen(buffer) 表示要发送的数据长度(以字节为单位)。

  • 0 是可选参数 flags,表示额外选项,默认设置为 0。

    // 3 请求http
    // hostname: github.com
    // resource /wangbojing
    char * http_send_request(const char *hostname, const char *resource) {
        char *ip = host_to_ip(hostname); //name-->ip
        int sockfd = http_create_socket(ip); //创建一个socket tcp连接
    
        char buffer[BUFFER_SIZE] ={0};
        sprintf(buffer, 
        "GET %s %s\r\n
        HOST: %s\r\n,
        %s\r\n\
        \r\n",
        resource, HTTP_VERSION, 
        hostname,
        CONNETION_TYPE
        );
    
        send(sockfd,buffer, strlen(buffer), 0);
    
        // 获取response, 因为非阻塞,可能还没返回所以recv是空的
    }
    

5 http项目 select使用讲解与http response接收

select监听判断 网络IO里有没有可读数据

多次recv拼起来到result 好多网络编程看不懂查

  1. fd_set fdread;, 
    FD_ZERO(&fdread);
    FD_SET(sockfd, &fread);
    

    这段代码是用于设置一个文件描述符集合,然后将 sockfd(socket 文件描述符)添加到该集合中。

    首先,fd_set fdread; 定义了一个文件描述符集合 fdread。

    接下来,FD_ZERO(&fdread); 会将 fdread 集合清空,初始化为空集。

    最后,FD_SET(sockfd, &fread); 将 sockfd 添加到 fdread 集合中。此操作表示将 sockfd 加入到待检查的读取文件描述符集合中。

    这段代码通常在使用 select() 或 epoll() 等 I/O 多路复用函数时使用,用于指定要监视的文件描述符。

  2. int selection = select(sockfd+1, fread, NULL, NULL, &tv); // 可读maxfd+1, 可读集合&rset,可写集合&wset, 错误集合&eset, 多长时间遍历一次所有IO 
    		if (!selection || !FD_ISSET(sockfd, &fdread)) {
    			break;
    		} else{
                memset(buffer,  0, BUFFER_SIZE);
                recv(sockfd, buffer, BUFFER_SIZE, 0); //sockfd读到buffer
                if(len ==0) break; //disconnect
            }
            result = realloc(result, (strlen(result) + len + 1) * sizeof(char));
            strncat(result, buffer, len);
    

    这段代码是一个基于 select() 函数的网络编程示例,用于检测套接字 sockfd 是否可读。下面是代码的解释:

    1. int selection = select(sockfd+1, fread, NULL, NULL, &tv); 这行代码调用了 select() 函数来等待 sockfd 的可读事件。第一个参数是文件描述符最大值加 1,表示要监视的最大文件描述符数(sockfd+1)。第二个参数是可读集合,即包含 sockfd 的 fd_set 结构体指针(fread)。
    2. if (!selection || !FD_ISSET(sockfd, &fdread)) { break; } 这个条件判断语句会在 select() 返回之后进行处理。如果 select() 返回值为 0 或者 sockfd 不在可读集合中,则跳出循环。
    3. memset(buffer, 0, BUFFER_SIZE); recv(sockfd, buffer, BUFFER_SIZE, 0); 这两行代码将 buffer 数组清零,并通过 recv() 函数从 sockfd 接收数据存入 buffer 中。
    4. if (len == 0) break; 如果 len(recv() 返回的结果)等于 0,说明连接已经断开,跳出循环。
    5. result = realloc(result, (strlen(result) + len + 1) * sizeof(char)); strncat(result, buffer, len); 这两行代码用于动态扩展 result 字符串,并将接收到的数据追加到 result 中。realloc() 函数重新分配了足够大小的内存空间来容纳 result 和 buffer 的内容,然后使用 strncat() 函数将 buffer 中的数据追加到 result 的末尾。

    总体来说,这段代码是一个基本的网络编程示例,使用 select() 函数实现了非阻塞式读取 sockfd 上的数据,并将接收到的数据存储在 result 字符串中。

//接上一次的函数里继续
    // 3 获取response, 因为非阻塞,可能还没返回所以recv是空的
    // select
    fd_set fdread;, 
    FD_ZERO(&fdread);
    FD_SET(sockfd, &fread);

    struct timeval tv;
    tv.tv_sec = 5; //等待秒数
    tv.tv_usec = 0; //等待微秒数

    char *result = malloc(sizeof(int));  //malloc的数据一定要memset0防止混乱数据,最后要free
	memset(result, 0, sizeof(int));
	

    while(1){
        int selection = select(sockfd+1, fread, NULL, NULL, &tv); // 可读maxfd+1, 可读集合&rset,可写集合&wset, 错误集合&eset, 多长时间遍历一次所有IO 
		if (!selection || !FD_ISSET(sockfd, &fdread)) {
			break;
		} else{
            memset(buffer,  0, BUFFER_SIZE);
            recv(sockfd, buffer, BUFFER_SIZE, 0); //sockfd读到buffer
            if(len ==0) break; //disconnect
        }
        result = realloc(result, (strlen(result) + len + 1) * sizeof(char));
        strncat(result, buffer, len);
    }
}

int main(int argc, char *argv[]) {

	if (argc < 3) return -1;

	char *response = http_send_request(argv[1], argv[2]);
	printf("response : %s\n", response);

	free(response);
	
}

6 http项目编译调试,网页请求与API接口请求

还行,调一下, 一个个调就行,有点耐心

gcc -o httprequest httprequest.c
./httprequest www.baidu.com /

/代表resource 首页所以只有/

没有东西 只有response:, 暂时没调出来

正常应该接受到源码网页右击view page source 或者CTRL+U

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/619476.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PC的体系结构

冯诺依曼体系结构 冯诺依曼体系结构&#xff0c;也称为冯诺依曼架构&#xff0c;是一种计算机架构的设计概念&#xff0c;由20世纪中叶的数学家和物理学家约翰冯诺依曼提出。这种架构的核心特点是将程序指令和数据存储在同一块可读写的存储器中。这样做的优点是简化了计算机的…

web前端之纯CSS实现简单酷炫的照片墙效果、排除元素的伪类、scale

MENU 效果htmlstylescale:not() 效果 html <div class"container"><div class"box"><img src"../../image/1_.jpg"></div><div class"box"><img src"../../image/2_.jpg"></div>…

AI办公自动化-用kimi把PDF文档按照章节自动拆分成多个docx文档

一个PDF文档很长&#xff0c;希望按照章节分拆成小文档。 可以在kimichat中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个编写拆分PDF文档的Python脚本的任务&#xff0c;具体步骤如下&#xff1a; 打开文件夹&#xff1a;D:\chatgpt图书\图书1&…

Zookeeper 注册中心:单机部署

序言 本文给大家介绍 Zookeeper 单机部署流程、 如何与 Spring 整合使用。除此之外&#xff0c;还有 Zookeeper 作为注册中心与 SpringCloud 的整合流程。 一、部署流程 官网下载 Zookeeper 安装包 解压安装包到指定目录 进入 apache-zookeeper-3.8.4-bin/conf 目录&…

LwIP 之九 详解 UDP RAW 编程、示例、API 源码、数据流

我们最为熟知的网络通信程序接口应该是 Socket。LwIP 自然也提供了 Socket 编程接口,不过,LwIP 的 Socket 编程接口都是使用最底层的接口来实现的。我们这里要学习的 UDP RAW 编程则是指的直接使用 LwIP 的最底层 UDP 接口来直接实现应用层功能。这里先来一张图,对 LwIP 内部…

YOLO数据集制作(二)|json文件转txt验证

以下教程用于验证转成YOLO使用的txt格式&#xff0c;适用场景&#xff1a;矩形框&#xff0c;配合json格式文件转成YOLO使用的txt格式脚本使用。 https://blog.csdn.net/StopAndGoyyy/article/details/138681454 使用方式&#xff1a;将img_path和label_path分别填入对应的图…

图鸟UI vue3:基于Vue3和UniApp的酷炫简洁UI框架

引言 随着前端技术的不断发展&#xff0c;开发效率和用户体验成为了前端开发中的两大关键因素。为了提高开发效率和提供更好的用户体验&#xff0c;各种UI框架应运而生。其中&#xff0c;TuniaoUI作为一款基于Vue3和UniApp开发的UI组件库&#xff0c;以其酷炫简洁的设计和丰富…

JVM调优:JVM中的垃圾收集器详解

JVM&#xff08;Java Virtual Machine&#xff09;垃圾收集器是Java虚拟机中的一个重要组件&#xff0c;负责自动管理Java堆内存中的对象。垃圾收集器的主要任务是找出那些不再被程序使用的对象&#xff0c;并释放它们占用的内存&#xff0c;以便为新的对象分配空间。这个过程被…

客户端机器访问服务端Harbor

书接上回&#xff1a;Docker私有仓库Harbor-CSDN博客 修改客户端机器名称 [roothost01 ~]# hostnamectl hostname client [roothost01 ~]# bash [rootclient ~]# 安装docker [rootclient ~]# yum -y install yum-utils.noarch [rootclient …

分布式任务调度框架xxl-job使用手册

官网地址和文档地址&#xff1a;https://www.xuxueli.com/xxl-job/ 一、快速入门 1.1 下载源码 https://github.com/xuxueli/xxl-job https://gitee.com/xuxueli0323/xxl-job 下载完成后有以下模块 1.2 初始化数据库 官方指定mysql8.0&#xff0c;但我是mysql5.7 执行/xxl…

Git系列:git tag 使用技巧

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

【web开发网页制作】Html+Css明星网页主题开发之邓超(5页面附源码)

HTMLCSS影视主题网页目录 &#x1f354;涉及知识&#x1f964;写在前面&#x1f367;一、网页主题&#x1f333;二、网页效果Page1、首页Page2、个人经历Page3、个人生活Page4、个人作品Page5、个人公益 &#x1f40b;三、网页架构与技术3.1 脑海构思3.2 整体布局3.3 技术说明书…

C++––初识C++

目录 一.绪言 1.什么是C 2.C语言和C的关系 2.1数据类型 2.2数据类型的长度 2.3变量和常量 2.4字符串操作 2.5判断和选择语句&#xff0c;循环语句 2.6逻辑运算符 2.7函数的声明和调用 2.8数组 2.9操作符 二.C入门的基本知识 1.命名空间 2.输入&输出 3.缺省…

Node.js全栈:从一个简单的例子开始

第一章&#xff1a;从一个简单的例子开始第二章&#xff1a;看官方文档的艺术第三章&#xff1a;浏览器显示一个网页 首先&#xff0c;在VSCode编辑器中打开一个没有任何文件的空目录&#xff0c;然后创建一个package.json文件。 为了方便大家复制&#xff0c;我把文件内容放到…

【C语言项目】贪吃蛇(下)

个人主页~ 源码在Gitee仓库~ 上一篇贪吃蛇&#xff08;上&#xff09;~ 贪吃蛇 四、核心的实现游戏测试1、GameStart&#xff08;1&#xff09;控制台窗口大小和名字设置&#xff08;2&#xff09;光标隐藏&#xff08;3&#xff09;打印欢迎界面&#xff08;4&#xff09;创建…

加入全球少儿编程运动:Scratch让每个孩子都能成为创造者(Scratch最新版客户端和初/中/高级学习资料整理分享)

文章目录 &#x1f4d6; 介绍 &#x1f4d6;&#x1f3e1; 演示环境 &#x1f3e1;&#x1f4d2; 文章内容 &#x1f4d2;&#x1f4dd; 安装与使用&#x1f4dd; 社区与资源 &#x1f388; 获取方式 &#x1f388;⚓️ 相关链接 ⚓️ &#x1f4d6; 介绍 &#x1f4d6; 你知道…

没有公网ip,如何实现外网访问内网?

目前拨号上网是最广泛的上网方式&#xff0c;这种方式优点是价格便宜&#xff0c;缺点是没有固定公网ip&#xff0c;每次重新您拨号ip地址都会变。如果有一台服务器&#xff0c;需要实现外网访问&#xff0c;在没有固定公网ip的环境下&#xff0c;该如何实现呢&#xff1f;使用…

2.4 输入和显示

本节必须掌握的知识点&#xff1a; 示例五源代码 代码分析 汇编解析 2.4.1 示例五 ■格式化输入函数scanf scanf函数可以从键盘读取输入的信息。scanf函数同样可以像printf函数那样&#xff0c;通过转换说明“%d”来限制函数只能读取十进制数。scanf函数的参数为可变参数…

外网如何访问内网?快解析

由于公网IP资源短缺&#xff0c;我们的电脑大多处于内网环境&#xff0c;如何在外网访问内网电脑&#xff0c;成为一个令人头疼的问题&#xff0c;下面我给大家推荐一个非常实用的方法。 1&#xff1a;访问快解析下载安装快解析服务器 2&#xff1a;运行软件&#xff0c;点击“…

08.4.grafana自定义图形并直接数据库取值

grafana自定义图形并直接数据库取值 自定义添加油表图形 选择gauge图形&#xff0c;并且配置对应设定值&#xff0c;点击应用 如图所示&#xff0c;可以看到仪表盘上的值是zabbix上取得值 配置grafana直接数据库取值 添加mysql数据源 添加后进行配置&#xff0c;我这…