当前位置: 首页 > article >正文

用套接字的UDP,TCP知道什么是HTTP吗?

文章目录

  • UDP和TCP
  • 七层网络架构
  • Omnipeek抓包分析举例
    • 图片备注
    • code
    • 参考code
  • HTTP协议的构成

UDP和TCP

UDP(User Datagram Protocol,用户数据报协议) 和 TCP(Transmission Control Protocol,传输控制协议) 是网络传输层协议
而我们的今天的主角HTTP(HyperText Transfer Protocol,超文本传输协议) 则是应用层协议

七层网络架构

七层网络架构简约描述

Omnipeek抓包分析举例

图片备注

page_0
page_1

code

struct ip_header {
    uint8_t  iph_ihl:4, iph_ver:4;
    uint8_t  iph_tos;
    uint16_t iph_len; // 2
    uint16_t iph_id;
    uint16_t iph_offset;
    uint8_t  iph_ttl;
    uint8_t  iph_protocol;
    uint16_t iph_checksum;
    uint32_t iph_saddr;
    uint32_t iph_daddr;
}__attribute__((__packed__));

struct udp_header {
    uint16_t udp_sport; // 源端口
    uint16_t udp_dport; // 目的端口
    uint16_t udp_len;   // UDP数据包长度
    uint16_t udp_checksum; // UDP校验和
};

// 伪头部结构(UDP校验和计算需要)
struct pseudo_header {
    uint32_t source_address;
    uint32_t dest_address;
    uint8_t placeholder;
    uint8_t protocol;
    uint16_t udp_length;
};

/// 求校验和Function
static uint16_t checksum(void *b, int len) {
    uint16_t *buf = b;
    uint32_t sum = 0;
    uint16_t result;

    // 计算 16 位反码加和
    for (sum = 0; len > 1; len -= 2)
        sum += *buf++;
    if (len == 1)
        sum += *(unsigned char *)buf;
    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    result = ~sum;
    return result;
}

int main(void)
{
	int ret = 0;
	struct sockaddr_in addr;
	
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr("192.168.1.1"); ;
	addr.sin_port = htons(0);  // 端口号对原始套接字通常没有意义   无论设置多少,都是会接受所有本地址下的所有端口信息
	
	int socket_raw = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
	ret = bind(socket_raw , (struct sockaddr *)&addr, sizeof (struct sockaddr));
	
	// ……
}

使用原始套接字:发送:需要自己从传输层协议包构造,接受:是从IP包开始的

参考code

	// struct ip_header *ip = (struct ip_header *)packet;
	// ip->iph_ihl = 5;               // IP 头部长度(单位是32位,即4字节)
	// ip->iph_ver = 4;                // 使用 IPv4
	// ip->iph_tos = 0x10;                // 服务类型(低延迟)
	// ip->iph_len = htons(sizeof(struct ip_header) + sizeof(struct udp_header) + snd_len); // IP数据包 总长度 (是包括传输层的数据的)
	// ip->iph_id = htons(54300);      // ID(标识一个数据包 不分段,所以可以随便设置)
	// ip->iph_offset = 0;             // 偏移量(不分段)
	// ip->iph_ttl = 64;               // TTL(最大跳转路由数)
	// ip->iph_protocol = IPPROTO_UDP;  // 协议类型 UDP
	// ip->iph_saddr = inet_addr(OEMINFO_DEFAULT_NET_IP); // 源 IP
	// ip->iph_daddr = cli_addr.sin_addr.s_addr; // 目标 IP 
	// ip->iph_checksum = 0;
	

	// 地址 https://docs.pingcode.com/baike/1281537

	// 填充 UDP 头部
	// struct udp_header *udp = (struct udp_header *)(packet + sizeof(struct ip_header));
	struct udp_header *udp = (struct udp_header *)(packet);
	if (prohdr->cid == 1 || prohdr->cid == 2 || prohdr->cid == 3 || prohdr->cid == 6 || prohdr->cid == 7 || prohdr->cid == 8 || prohdr->cid == 10 || prohdr->cid == 11) {
		udp->udp_sport = htons(OEMINFO_DEFAULT_BASE_PORT);  // 源端口
	} else {
		udp->udp_sport = htons(OEMINFO_DEFAULT_BASE_PORT + 1);  // 源端口
	}
	udp->udp_dport = htons(cli_addr.sin_port);  // 目标端口
	udp->udp_len = htons(sizeof(struct udp_header) + snd_len);  // UDP 数据包长度
	udp->udp_checksum = 0; // 初始值 0,稍后计算 (伪头部、UDP头部、数据部分)

	

	// 伪头部结构 ( 只为计算校验和 ) 
	struct pseudo_header psh;
	psh.source_address = inet_addr(OEMINFO_DEFAULT_NET_IP);
	psh.dest_address = cli_addr.sin_addr.s_addr;
	psh.placeholder = 0; // 占位符
	psh.protocol = IPPROTO_UDP;
	psh.udp_length = htons(sizeof(struct udp_header) + snd_len); // UDP 头 + 数据

	int psize = sizeof(struct pseudo_header) + sizeof(struct udp_header) + snd_len;
	
	// 先填充
	// uint8_t *data = packet + sizeof(struct ip_header) + sizeof(struct udp_header); // 往后挪,移出位置写数据
	uint8_t *data = packet + sizeof(struct udp_header); // 往后挪,移出位置写数据
	memcpy(data, buffer, snd_len);


	// 验证数据是否在数据本该的位置上
	printf("data[0] = %02x, data[1] = %02x, data[2] = %02x, data[3] = %02x\r\n", data[0], data[1], data[2], data[3]);

	pseudo_packet = malloc(psize);
	if (pseudo_packet == NULL) {
		printf("Memory allocation failed\n");
		return;
	}
	memcpy(pseudo_packet, (uint8_t *)&psh, sizeof(struct pseudo_header));
	memcpy(pseudo_packet + sizeof(struct pseudo_header), udp, sizeof(struct udp_header));
	memcpy(pseudo_packet + sizeof(struct pseudo_header) + sizeof(struct udp_header), data, snd_len);

	// 计算 UDP 校验和
	// ip->iph_checksum = checksum(packet, sizeof(struct ip_header)); // IP 头部校验和
	udp->udp_checksum = checksum(pseudo_packet, psize);

	// 后填充数据
	// memcpy(packet, ip, sizeof(struct ip_header)); // 往后挪,移出位置写IP头
	// memcpy(packet + sizeof(struct udp_header), buffer, snd_len); // 往后挪,移出位置写UDP头
	
	
	free(pseudo_packet);
	pseudo_packet = NULL;

	int ret = -1;
	while(ret <= 0) {
		ret =  sendto(sock, packet, sizeof(struct udp_header) + snd_len, 0, (struct sockaddr *)&cli_addr, addr_len);
	}
	if (ret > 0) {
		printf("send success ,send size is %d\r\n", ret);
	}
	memset(packet, 0, sizeof(packet));

HTTP协议的构成

HTTP包,即HTTP报文,是HTTP协议中传输数据的基本单位。

结构: 头 \r\n\r\n 正文
栗子:

POST http://example.com/upload HTTP/1.0
Host: example.com
Accept-Encoding: ''
Content-Type: image/jpeg
Content-Length: 10240
deviceId: 1234567890
deviceToken: abcdefg
action: start
sid: 123
stream: 1

同下:

uint8_t http_uri[1024] = {0};
sprintf(http_uri, "POST %s HTTP/1.0\r\nHost: %s\r\nAccept-Encoding: ''\r\nContent-Type: image/jpeg\r\nContent-Length: %d\r\n"
						"deviceId: %s\r\ndeviceToken: %s\r\naction: start\r\nsid: %d\r\nstream: 1\r\n\r\n", ……);

先到这,关注一下,下一节继续讲HTTP~


http://www.kler.cn/a/450134.html

相关文章:

  • 华为浏览器(HuaweiBrowser),简约高效上网更轻松
  • ROS1入门教程6:复杂行为处理
  • 谷歌浏览器的网络安全检测工具介绍
  • 数据库操作【JDBC HIbernate Mybatis】
  • Day13 苍穹外卖项目 工作台功能实现、Apache POI、导出数据到Excel表格
  • Spring Security 6 系列之七 - 自定义异常管理
  • Apache解析漏洞(apache_parsing_vulnerability靶场攻略CVE-2017-15715靶场攻略)
  • 服务平滑发布与线上验证
  • CNN、RNN、LSTM和Transformer之间的区别和联系
  • 安装CPU版的torch(清华源)
  • 经典案例PPT | 大型水果连锁集团新零售数字化建设方案
  • Ubuntu下C语言操作kafka示例
  • 基于GRU门控循环神经网络的多分类预测【MATLAB】
  • npm error code ETIMEDOUT
  • 【Prometheus】【实战篇(七)】在 Grafana 中配置数据源并使用 Prometheus Node Exporter
  • 【研究生必备|学术会议|高录用|见刊后1个月检索】第三届材料科学与智能制造国际学术会议(MSIM2025)
  • 【橘子微服务】spring cloud function的编程模型
  • Webhook 是什么?详解其工作原理
  • 日文医学论文如何翻译
  • EMQX构建简易的云服务
  • 节日需求激增:如何抓住家居用品和圣诞装饰品市场的商机?
  • Scala——身份证号码查询籍贯
  • ASP.NET |日常开发中常见问题归纳讲解
  • Nginx限速原理、配置与测试
  • 插入块(数据库)、预览图 错误调试
  • python 定时任务管理封装