基于HTTP GET方式获取网络时间的实现

上一节,我们介绍了基于NTP服务器获取网络时间的例子,但在有些情况下,比如我最近在使用RNDIS协议通过4G模块上网,这个协议不支持UDP协议,所以就用不了NTP服务器。或者有时候我们需要有更多的网络时间获取方式,以保证系统100%能获取到网络时间。本节就来介绍一下更通用的获取网络时间的方式:HTTP GET。

文章目录

  • 1 HTTP GET原理
    • 1.1 网络中的工作流程
    • 1.2 HTTP GET请求组成部分
    • 1.3 测试
  • 2 代码实现
    • 2.1 实现步骤
    • 2.2 完整代码
  • 3 结果
  • 4 总结

1 HTTP GET原理

本节的原理实际上就是类似浏览器访问网站一样获取网站的数据,只需要找到一个能显示时间的网站就行了。下面就来了解一下使用socket请求HTTP GET网络数据的原理。

1.1 网络中的工作流程

  1. 用户发起请求: 用户通过浏览器或应用向服务器发送一个HTTP GET请求。
  2. 服务器处理请求: 服务器接收到请求后,解析URL和头部信息,根据请求的资源进行处理。
  3. 发送响应: 服务器将请求的数据(如HTML页面、图片等)打包在HTTP响应中返回给客户端。
  4. 客户端处理响应: 客户端(通常是浏览器)接收响应并根据需要渲染或处理数据。

1.2 HTTP GET请求组成部分

  • 请求行: 包括方法(GET)、请求的URI和HTTP版本。
  • 请求头: 包含请求的元数据,如用户代理信息、接受的内容类型等。
  • 空行: 请求头后面跟一个空行,表示请求头的结束。
  • 请求体: GET请求通常没有请求体,因为请求的数据包含在URI中。

下面是一些常见的HTTP请求头字段,这些字段在HTTP GET请求中经常使用:

1. Host

  • 描述Host 请求头指定了被请求资源的互联网主机和端口号,它通常由URI提供。由于一个服务器可能寄存多个域名,Host 请求头用来指定请求的是哪个域名。
  • 示例:如果请求 http://www.example.com/index.html,那么 Host 请求头将是:
Host: www.example.com

2. User-Agent

  • 描述User-Agent 请求头包含了一个特征字符串,用于让服务器识别客户端使用的操作系统,浏览器和浏览器版本等信息。这可以帮助服务器提供与设备兼容的响应。
  • 示例:一个典型的 User-Agent 请求头可能看起来像这样:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36

3. Accept

  • 描述Accept 请求头用于告诉服务器,客户端能够处理哪些媒体类型。服务器可以根据这个头部信息决定返回什么类型的内容。
  • 示例:表明客户端可以处理HTML和XML,以及它们的特定版本:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

4. Accept-Language

  • 描述Accept-Language 请求头用于告诉服务器,客户端希望优先接收哪种自然语言(如英语、中文等)。服务器可以据此返回相应语言的内容,实现本地化。
  • 示例
Accept-Language: en-US,en;q=0.5

5. Accept-Encoding

  • 描述Accept-Encoding 请求头用于告诉服务器,客户端支持哪些压缩格式。服务器可以选择一个适合的压缩方法,以减小响应数据的体积,提高传输效率。
  • 示例
Accept-Encoding: gzip, deflate, br

6. Connection

  • 描述Connection 请求头用于控制客户端和服务器之间的连接管理,常用的值有 keep-aliveclosekeep-alive 告诉服务器保持连接打开,以便未来的请求可以使用同一连接,close 则相反。
  • 示例
Connection: keep-alive

示例: 一个HTTP GET请求的结构

GET /example?page=1 HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

当然,并非所有请求头都是必须的。某些头部信息如 User-Agent、Accept、Accept-Language 等是可选的,这些头部提供了关于客户端偏好和能力的信息,可以帮助服务器更优化地响应请求,但不包含这些头也不会阻止请求的基本功能。只有在特定场景下,例如多域托管、特定内容协商或需管理连接时,才需要特定的请求头。

1.3 测试

我们直接在电脑上用TCP客户端测试一下这样是否可行,首先我们获取服务器的IP:
在这里插入图片描述
然后我们连接这个IP,HTTP端口号一般为80,并发送请求报文:
在这里插入图片描述
可以看到,我们请求访问网页后,对方返回了HTTP头和网页内容,即我们成功获取了网页中的时间。

2 代码实现

这里在Linux环境下为例对HTTP网络时间进行获取,使用标准的POSIX/BSD套接字编程,这样如果想在单片机中LwIP实现的话,也可以直接使用。

2.1 实现步骤

1、HTTP时间服务端地址
这里以苏宁的时间服务器为例:https://quan.suning.com/getSysTime.do在这里插入图片描述HTTP的端口一般都是80:

#define SERVER_PORT 80
#define SERVER_HOST "quan.suning.com"

2、创建套接字、解析域名
实际上HTTP也是基于TCP协议实现的,整个过程无非就是建立一个TCP连接,所以首先我们就是创建一个套接字。接着像苏宁这种大网站,一般会根据不同的地区分配不同的IP服务器以分担服务器负担,所以IP在不同地区解析出来都不一样,这里我们做一下域名DNS解析,用gethostbyname函数将域名解析为IP。

int sockfd;
struct hostent *server;

// 创建socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
// 获取服务器的地址
server = gethostbyname(SERVER_HOST);

3、建立连接
填充一下服务端结构体,建立连接。

// 填充服务器地址结构体
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
memcpy(&serveraddr.sin_addr.s_addr, server->h_addr, server->h_length);
serveraddr.sin_port = htons(SERVER_PORT);
// 连接到服务器
connect(sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr));

4、请求网页数据并读取

#define REQUEST "GET /getSysTime.do HTTP/1.1\r\nHost: quan.suning.com\r\n"   \
				"Connection: close\r\n\r\n"
char response[4096];
// 发送GET请求
write(sockfd, REQUEST, strlen(REQUEST);
read(sockfd, response, sizeof(response) - 1) ;

简单分析一下这个请求头

  • Host: quan.suning.com
    • 这个头是必需的,它指定了请求发送到的服务器的域名。在HTTP/1.1版本中,每个请求都必须包含Host头,因为一个服务器上可能托管多个域,服务器通过这个头部信息来确定要访问的具体域。
  • Connection: close
    • 这个头部控制着连接的管理,close 的值意味着一旦请求完成后,客户端和服务器之间的连接将关闭,不会用于后续的请求。

2.2 完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define SERVER_PORT 80
#define SERVER_HOST "quan.suning.com"
#define REQUEST "GET /getSysTime.do HTTP/1.1\r\nHost: quan.suning.com\r\nConnection: close\r\n\r\n"

int main() {
    int sockfd;
    struct sockaddr_in serveraddr;
    struct hostent *server;
    char response[4096];

    // 创建socket
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("ERROR opening socket");
        exit(1);
    }

    // 获取服务器的地址
    server = gethostbyname(SERVER_HOST);
    if (server == NULL) {
        fprintf(stderr, "ERROR, no such host\n");
        exit(0);
    }

    // 填充服务器地址结构体
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    memcpy(&serveraddr.sin_addr.s_addr, server->h_addr, server->h_length);
    serveraddr.sin_port = htons(SERVER_PORT);

    // 连接到服务器
    if (connect(sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0) {
        perror("ERROR connecting");
        exit(1);
    }

    // 发送GET请求
    if (write(sockfd, REQUEST, strlen(REQUEST)) < 0) {
        perror("ERROR writing to socket");
        exit(1);
    }

    // 读取响应
    memset(response, 0, sizeof(response));
    if (read(sockfd, response, sizeof(response) - 1) < 0) {
        perror("ERROR reading from socket");
        exit(1);
    }

    // 打印响应
    printf("%s\n", response);

    // 关闭socket
    close(sockfd);
    return 0;
}

注意,苏宁的网站有流量控制,有时候访问会出现系统忙,一般再请求一次即可,这个自己在代码中判断。

3 结果

编译后运行:
在这里插入图片描述
可以看到,结果和用TCP客户端上位机获取的一样,我们只需要做一些文本的操作就能获取到当前的时间了。

4 总结

本篇博客介绍了如何在Linux下使用C语言和Socket API发起HTTP GET请求。这个示例程序可以扩展到其他类型的HTTP请求和不同的API服务。如果不想用苏宁的服务器,可以随便请求一个网站和不存在的网页,如果网站用的是nginx的话,访问不存在的网页也会返回一个nginx时间。

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

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

相关文章

python数据分析——seaborn绘图2

参考资料&#xff1a;活用pandas库 # 导入库 import pandas as pd import matplotlib.pyplot as plt import seaborn as sns tipspd.read_csv(r"...\seaborn常用数据案例\tips.csv") print(tips.head()) 1、成对关系表示 当数据大部分是数据时&#xff0c;可以使用…

AI图像生成-调整

一、两张图画风不相似 2、在两张图的共同输出口新添加一个空白正面提示词板块和条件合并板块 二、预处理插件&#xff08;提取人物姿态&#xff09; 1、新建节点-》ControlNet预处理器-》面部与姿态-》Openpose姿态预处理器 2、添加上传图片板块与预览图片板块 3、提取姿态 右…

数据库学习之select语句练习

目录 素材 练习 1、显示所有职工的基本信息。 结果 2、查询所有职工所属部门的部门号&#xff0c;不显示重复的部门号。 结果 3、求出所有职工的人数。 结果 4、列出最高工和最低工资。 结果 5、列出职工的平均工资和总工资。 结果 6、创建一个只有职…

【全开源】房屋出租出售预约系统支持微信小程序+H5+APP

一款基于FastAdminThinkPHPUniapp开发的房屋出租出售预约系统&#xff0c;支持小程序、H5、APP&#xff1b;包含房客、房东(高级授权)、经纪人(高级授权)三种身份。核心功能有&#xff1a;新盘销售、房屋租赁、地图找房、小区找房&#xff0c;地铁找房等方式。 特色功能&#…

Salesforce AI研究: 从奖励建模到在线RLHF工作流

摘要 该研究在本技术报告中介绍了在线迭代基于人类反馈的强化学习(Online Iterative Reinforcement Learning from Human Feedback, RLHF)的工作流程,在最近的大语言模型(Large Language Model, LLM)文献中,这被广泛报道为大幅优于其离线对应方法。然而,现有的开源RLHF项目仍然…

【爬虫之scrapy框架——尚硅谷(学习笔记two)--爬取电影天堂(基本步骤)】

爬虫之scrapy框架--爬取电影天堂——解释多页爬取函数编写逻辑 &#xff08;1&#xff09;爬虫文件创建&#xff08;2&#xff09;检查网址是否正确&#xff08;3&#xff09;检查反爬&#xff08;3.1&#xff09; 简写输出语句&#xff0c;检查是否反爬&#xff08;3.2&#x…

初识鸿蒙之ArkTS基础

前言 学习一种应用程序开发&#xff0c;需要从这种程序的开发语言开始&#xff0c;比如说Android开发从入门到放弃&#xff0c;肯定是从Java基础或者是Kotlin语言基础开始学习的&#xff0c;IOS程序开发也肯定是从object-c开始学习的。鸿蒙软件开发也不例外&#xff0c;如果做…

二叉树的前序遍历(leetcode)

144. 二叉树的前序遍历 - 力扣&#xff08;LeetCode&#xff09; 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 这道题的启发性真的很强 &#xff0c;这里必须传入i的指针进去&#xff0c;下一次栈帧i&#xff0c;但回到了上一层i又变回到了原来的i&#…

办公园区建筑科技风效果(html+threejs)

办公楼科技风(Htmlthreejs) 初始化三维场景 function init() {container document.getElementById(container);camera new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 150000000);camera.position.set(550, 600, 690);scene new THREE.Sce…

短视频的拍摄方式有哪些:四川京之华锦信息技术公司

创意与技术并存的艺术之旅 在数字媒体高速发展的今天&#xff0c;短视频已经成为人们获取信息、表达情感、展示才艺的重要窗口。从社交平台到新闻资讯&#xff0c;再到教育娱乐&#xff0c;短视频无处不在&#xff0c;其独特的魅力和广泛的传播力让人们对它的拍摄方式产生了浓…

应急响应-Windows-挖矿病毒

随着虚拟货币市场的繁荣&#xff0c;挖矿病毒已成为网络安全领域一大挑战。该类病毒利用计算机资源进行加密货币的挖掘&#xff0c;给个人用户和企业网络带来了严重的安全风险。本文将针对挖矿病毒的应急响应和防范措施进行分析和总结。 一.判断挖矿病毒 服务器突然发现CPU资…

CTF例题:[SWPU2019]Web1(无列名注入)

网址&#xff1a;BUUCTF在线评测 搜索web1 启动靶机 点击链接进入题目 进入题目后发现有登录和注册接口&#xff0c;直接注册登录。 首先通过1进行测试&#xff0c;查看是否有注入点 出现报错&#xff0c;说明可能存在注入点 然后继续测试发现该服务器过滤了&#xff1a; or、…

Android 逆向

一、apk 查壳工具 ApkScan-PKID 相关APK文件可以在 豌豆荚 官网下载 ApkScan-PKID查壳工具 下载 - 简书 (jianshu.com) 二、脱壳工具&#xff1a;frida 1、Android端配置 frida-server&#xff1a; 该步骤需要使用到 adb&#xff0c;操作Android文件 Releases frida/frid…

前端已死? Bootstrap--CSS组件

目录 Bootstrap 下载 Bootstrap--全局CSS样式 栅格系统 栅格参数 正常显示 实例 代码演示: 排版 代码演示 表格 代码演示 表单 代码演示 等等...(文档很清晰了) Bootstrap--组件 结合演示:(页面) Bootstrap Bootstrap v3 中文文档 Bootstrap 是最受欢迎的 HT…

ubuntu18.04 运行ur5机械臂

视觉抓取初探索1-UR5机械臂抓取仿真 - 知乎 抓取不止&#xff01;Ubuntu 18.04下UR5机械臂搭建Gazebo环境&#xff5c;开源分享_哔哩哔哩_bilibili 源码地址&#xff1a;GitHub - Geo-JTao/UR5_gripper_camera_gazebo: 在Ubantu18.04中搭建Gazebo仿真环境 遇到问题&#xff1…

Volatile解决内存不可见性

一、多线程下变量的不可见性 在多线程并发执行下&#xff0c;多个线程修改共享的成员变量&#xff0c;会出现一个线程修改了共享变量的值后&#xff0c;另一个线程不能直接 看到该线程修改后的变量的最新值。 我们首先让子线程去更改变量flag的值为true,主线程通过判断后执行。…

运维别卷系列 - 云原生监控平台 之 04.prometheus 查询语句 promql 实践

文章目录 [toc]PromQL 简介什么是时间序列 PromQL 数据类型即时向量 Instant vector范围向量 Range vectorTime DurationsOffset modifier modifier 浮点值 Scalar字符串 String PromQL FUNCTIONSfloor()irate()rate()round()sort()sort_desc() PromQL 运算符算术运算符比较运算…

C语言中的循环队列与栈、队列之间的转换实现

引言 在数据结构的学习中&#xff0c;栈&#xff08;Stack&#xff09;和队列&#xff08;Queue&#xff09;是两个非常重要的概念。它们分别遵循着后进先出&#xff08;LIFO&#xff09;和先进先出&#xff08;FIFO&#xff09;的原则。在某些情况下&#xff0c;我们可能需要…

用友NC printBill 任意文件读取/删除漏洞复现(XVE-2024-10609)

0x01 产品简介 用友NC是一款企业级ERP软件。作为一种信息化管理工具,用友NC提供了一系列业务管理模块,包括财务会计、采购管理、销售管理、物料管理、生产计划和人力资源管理等,帮助企业实现数字化转型和高效管理。 0x02 漏洞概述 用友NC printBill 接口处存在任意文件读…

PDF编辑阅读器PDF Expert for Mac v3.10.1中文激活版

PDF Expert for Mac是一款易于使用的 PDF 编辑器和注释器&#xff0c;专为 Mac 设备设计。它允许用户轻松查看、编辑、签名、注释和共享 PDF。该软件使用户能够向他们的 PDF 添加文本、图像、链接和形状&#xff0c;突出显示和标记文本&#xff0c;填写表格以及签署数字文档。它…