10. Linux下实现简单的http客户端请求

这篇具有很好参考价值的文章主要介绍了10. Linux下实现简单的http客户端请求。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文Linux下实现简单的http客户端请求

HTTP(超文本传输协议)是一种用于在网络上进行数据通信的协议。HTTP 协议定义了客户端和服务器之间如何交换信息,包括请求和响应格式、使用的方法、状态码等。
在 HTTP 协议中,资源(Resource)指的是由 URL (统一资源定位符)所标识的任意可用于访问的信息。这些信息可以是各种不同类型的数据,例如:HTML 页面、图片、音频、视频等多媒体文件、JavaScript 文件、样式表文件(CSS)、XML 文件、JSON 数据。
要完成一个完整的 HTTP 网络通信过程,需要使用以下一系列函数

  1. socket():创建套接字。

  2. connect():连接到指定的服务器。

  3. send():向服务器发送请求报文。

  4. listen():监听(多个)io里面有没有可读(或可写)的数据

  5. recv():从服务器接收响应报文。

  6. close():关闭套接字,释放资源。

简单的http客户端请求主要函数如下,详细可看代码里面的注释

  • char *host_to_ip(const char*hostname):该函数用于将主机名(hostname)转换为 IP 地址。
  • int http_create_socket(char *ip):该函数创建一个 TCP 套接字,并连接到指定的 IP 地址和端口号上。
  • char *http_send_request(const char *hostname,const char *resource):该函数发送 HTTP 请求并获取响应结果。

编译指令文章来源地址https://www.toymoban.com/news/detail-565350.html

zxmgcc -o http http.c
./http www.baidu.com /
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>

//Linux下的头文件
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>


#define BUFFER_SIZE     4096
#define HTTP_VERSION    "HTTP/1.1"
#define CONNETION_TYPE "Connection: close\r\n"

// /*该函数用于将主机名(hostname)转换为 IP 地址。它首先调用 gethostbyname 函数
// 获取主机名对应的地址信息结构体,然后从中提取出 IP 地址信息,并返回一个指向字符串类型的 IP 地址。*/
char *host_to_ip(const char*hostname){
    /*gethostbyname用于通过主机名获取主机的IP地址信息,
    并返回一个hostent结构体类型的指针,该结构体包含了主机名、别名和IP地址等信息。*/
    struct hostent *host_entry = gethostbyname(hostname);

    /*inet_ntoa()函数是一个在网络编程中常用的函数,它可以将一个32位整数IP地址转换成标准的点分十进制形式
    struct in_addr是一个C语言中的数据结构,用于表示32位IPv4地址。*/
    if (host_entry){
        //h_addr_list 是指向主机IP地址列表的指针,其类型为 char **
        return inet_ntoa(*(struct in_addr*)*host_entry->h_addr_list);
    }
    return NULL;
}

/*该函数创建一个 TCP 套接字,并连接到指定的 IP 地址和端口号上。它首先调用 socket 函数创建套接字,
然后调用 connect 函数连接到目标地址。如果成功则返回套接字文件描述符,否则返回 -1。*/
int http_create_socket(char *ip){
    int sockfd=socket(AF_INET,SOCK_STREAM,0);

    //sockaddr_in 用于表示 IPv4 地址和端口号
    struct sockaddr_in sin={0}; //
    sin.sin_family = AF_INET;   //指定 IP 地址的协议族
    sin.sin_port=htons(80);  //表示端口号
    sin.sin_addr.s_addr=inet_addr(ip);//表示 IP 地址,inet_addr作用与inte_ntoa相反

    /*在网络编程中,由于不同协议族(如IPv4、IPv6等)使用不同的地址结构体,为了保证代码的通用性和可移植性,
    在函数调用时需要将特定协议族所对应的地址结构体指针转换为通用的 sockaddr 结构体指针。
    因此,当我们想要将一个特定协议族(如IPv4)的地址结构体传递给一个接受 sockaddr 结构体参数的函数时,
    就需要使用 (struct sockaddr*)&sin 进行类型强制转换,以避免编译器报错。*/
    if ( 0!= connect(sockfd,(struct sockaddr*)&sin,sizeof(struct sockaddr_in))){
        return -1;
    }

    //将 sockfd 文件描述符设置为非阻塞模式
    fcntl(sockfd, F_SETFL, O_NONBLOCK);

    return sockfd;
}

/*该函数发送 HTTP 请求并获取响应结果。它首先通过 host_to_ip 函数将主机名转换为 IP 地址,
然后使用 http_create_socket 函数创建套接字并连接到目标服务器。接着构建 HTTP 请求报文,
并使用 send 函数将其发送给服务器。最后等待服务器响应并读取响应结果。*/
char *http_send_request(const char *hostname,const char *resource){
    char *ip=host_to_ip(hostname);
    int sockfd=http_create_socket(ip);

    char buffer[BUFFER_SIZE]={0};

    //HTTP协议中使用的行结束符是 "\r\n" ,每个字段之间需要用两个连续的回车符和换行符 "\r\n\r\n" 分隔开来
	sprintf(buffer, "GET %s %s\r\nHost: %s\r\n%s\r\n\r\n",
        resource, HTTP_VERSION, hostname, CONNETION_TYPE);


    /*如果在使用 UDP 协议进行通信或者需要对多个目标地址进行发送数据操作,则应该选择使用 sendto 函数;
    如果在使用 TCP 协议进行通信且只涉及一个目标地址,则可以选择使用 send 函数。*/
    send(sockfd,buffer,strlen(buffer),0);


    /*fd_set 是一个数据类型,可以同时监视多个文件描述符的状态,比如可读、可写或者异常等。
    在使用前必须先通过FD_ZERO宏清空,并使用FD_SET来添加或删除其中的文件描述符*/
    fd_set fdread;
    FD_ZERO(&fdread);
    FD_SET(sockfd,&fdread);

    /*timeval 结构体是一个用于表示时间的结构体,tv_sec 表示秒数,tv_usec 表示微秒数*/
    struct timeval tv;
    tv.tv_sec=5;
    tv.tv_usec=0;

    char *result=malloc(sizeof(int));
    memset(result,0,sizeof(int));
    while (1){
        /*select函数可以监听多个文件描述符(包括Socket),并等待其中任意一个或多个文件描述符上有I/O事件发生时通知调用者
        通过使用select函数,程序可以同时监听多个I/O事件,并且只要有任何一个事件发生了变化就会被立即通知。
        这样可以大大提高程序的性能和响应速度,避免阻塞或死循环等问题*,具体参数分别如下:
        nfds:需要监听的文件描述符最大值+1。即所有待监听文件描述符中最大的那个数加一。
        readfds:指向fd_set类型的指针,用于设置需要检查可读性的文件描述符集合。
        writefds:指向fd_set类型的指针,用于设置需要检查可写性的文件描述符集合。
        exceptfds:指向fd_set类型的指针,用于设置需要检查异常条件(错误)的文件描述符集合。
        timeout:等待超时时间。如果为NULL,则表示无限等待;如果为0,则表示立即返回。*/
        int selection=select(sockfd+1,&fdread,NULL,NULL,&tv);
        if( !selection || !FD_ISSET(sockfd,&fdread)){
            break;
        }
        else{
            //buffer之前已经被send之后,需要清空
            memset(buffer,0,BUFFER_SIZE);
            int len=recv(sockfd,buffer,BUFFER_SIZE,0);
            if (len==0){
                break;
            }
            
            result=realloc(result,(strlen(result)+len+1)*sizeof(char));
            strncat(result,buffer,len); //strncat()将指定长度的字符串追加到目标字符串末尾
        }
    }
    return result;
}


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);
	
}

到了这里,关于10. Linux下实现简单的http客户端请求的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Linux系统编程,使用C语言实现简单的FTP(服务器/客户端)

    Linux系统编程,使用C语言实现简单的FTP(服务器/客户端)

    前言 跟着上官社长 陈哥花了一个月的时间终于把Linux系统编程学的差不多了,这一个月真的是头疼啊,各种bug,调的真心心累,不过好在问题都解决掉了,在此也感谢一下答疑老师,给我提供了很多的思路,本文章是对前段时间学习Linux,做一个小小的总结,才疏学浅,只学

    2024年02月12日
    浏览(12)
  • java代码构建简单http服务器和客户端

    java代码构建简单http服务器和客户端

    初识http a、超文本传输 、应用层的面向对象的协议,概念介绍网上资源一大堆,关键是基于TCP/IP通信协议来传递数据。 b、一开始接触web项目,都是先接触的servlet,tomcat服务器默认实现的一套http规范,提供了基础服务和组件环境,直接拿到请求、构建正文、响应客户端 然而

    2024年02月10日
    浏览(16)
  • `accept` 是一个 HTTP 请求头字段,用于指定客户端可接受的内容类型

    `accept` 是一个 HTTP 请求头字段,用于指定客户端可接受的内容类型

    accept 是一个 HTTP 请求头字段,用于指定客户端可接受的内容类型。在 JavaScript 中,可以使用 fetch API 发送带有 Accept 头的请求。例如: 续写 当然可以,以下是一些关于 accept 请求头的更多信息: 使用不同的内容类型 除了 application/json ,你还可以使用其他内容类型来指定客户

    2024年02月22日
    浏览(12)
  • Http 响应头 Transfer-Encoding : chunked 导致 浏览器客户端请求错误问题

    Http 响应头 Transfer-Encoding : chunked 导致 浏览器客户端请求错误问题

    生产环境服务器规划如下 服务器 类型 网络环境 cal.com nginx 外网 192.168.7.15:9200 tomcat 内网 192.168.7.16:9200 tomcat 内网 sdd.com nginx 内网 192.168.7.15:9100 tomcat 内网 192.168.7.16:9100 tomcat 内网 192.168.7.15和192.168.7.16是做个负载均衡。目前的需求是用户访问外网的cal.com 返回 内网 192.168.7.15:9

    2024年02月15日
    浏览(12)
  • JAVA使用WebSocket实现多客户端请求

    工作前提:两个服务之间实现聊天通讯,因为介于两个服务,两个客户端 方案1:多个服务端,多个客户端,使用redis把用户数据ip进行存储,交互拿到redis数据进行推送 方案2: 一个服务端,多个客户端,拿到客户端的id和需要推送的id进行拼接存储 此文章使用的是方案2 1. 引

    2024年02月11日
    浏览(11)
  • linux搭建http源【服务端和客户端详细说明】

    linux搭建http源【服务端和客户端详细说明】

    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 [root@master ~]# 关闭防火墙和selinux firewall的话,直接 systemctl stop firewalld 即可 如果使用的是iptables,则吧firewalld替换成iptables [root@master ~]# systemctl is-active firewalld active [root@master ~]# [root@master ~]# systemctl stop firewalld [root@master ~]# [root@m

    2024年04月13日
    浏览(16)
  • 客户端请求+返回 服务端之间的请求和返回 实现rpc通信

    背景:         1.无论什么类型的游戏,我们都会有rpc通信的需求。         2.由于客户端直连的是游戏服,如果工会,匹配之类的服务是单独的服务的话,必然要进行游戏服到业务服之间的转发,我们是否需要再转发时单独定义Req和Res就是我们考虑到的需求。         3.在

    2024年01月25日
    浏览(6)
  • linux搭建http源【服务端和客户端详细说明(1)

    linux搭建http源【服务端和客户端详细说明(1)

    我下面的HTTP配置使用的包就是iso镜像里面的包【同理,我们只要会这种方式以后,使用什么包都一样,可以自己在网上下载自己需要的包和依赖,然后通过这种方式配置成http源,然后就可以直接使用yum安装了,这样的好处是解决软件在安装的时候会有许多依赖包这个繁琐的

    2024年04月11日
    浏览(12)
  • Linux 基于 TCP 协议的简单服务器-客户端应用

    Linux 基于 TCP 协议的简单服务器-客户端应用

    目录 一、相关函数  1、listen() 2、accept() 3、connect()  4、两种IP地址转换方式  5、TCP和UDP数据发送和接收函数对比 5、log.hpp自定义记录日志 二、udp_server.hpp单进程版本 三、tcp_server.cc 四、Telnet客户端(代替tcp_client.cc) 五、多进程实现udp_server.hpp 1、多进程版本一 2、tcp_client.

    2024年04月27日
    浏览(16)
  • 使用HTTP/2实现服务端主动推送消息给客户端

    使用HTTP/2实现服务端主动推送消息给客户端

    77. 使用HTTP/2实现服务端主动推送消息给客户端 HTTP/2 协议的服务器主动推送机制是通过服务器在接收到客户端请求后,主动向客户端推送相关资源的方式来实现的。下面将详细解释如何在服务器端和客户端实现 HTTP/2 的服务器主动推送,并给出相应的代码示例。 客户端实现:

    2024年02月11日
    浏览(16)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包