recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);/函数简单了解

部署运行你感兴趣的模型镜像

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recvfrom(int s, void*buf, size_t len , int flags, struct sockaddr*from , socklen_t *fromlen);

第1个参数s代表正在监听的端口的套接口文件描述符,它是由函数socket()生成的

第2个参数buff表示接收数据缓冲区, 接收到的数据将放在这个指针所指向的内存空间中

第3个参数len表示接收数据缓冲区大小,系统根据这个值来确保接收缓冲区的安全,防止溢出

第4个参数from是指向本地的数据结构sockaddr_in 的指针,发送数据时发送方的地址信息放在这个结构中

第5个参数fromlen表示第4个参数的所指内容的长度,可以使用sizeof(struct sockaddr_in)来获得。

当函数陷入内核中时,执行long sys_recvfrom(int fd, , void __user *ubuf, size_t size, int __user*addr_len)

系统调用函数sys_recvfrom主要查找文件描述符对应的内核socket结构,建立一个消息结构,将用户空间的地址缓冲区指针和数据缓冲区指针打包到消息队列中,在套接字文件描述符对应的数据链中查找对应的数据,将数据复制到消息中,销毁数据链中的数据,将数据复制到应用层的空间中, 减少文件描述符的引用计数。

sys_recvfrom()调用函数 sockfd_lookup_light() 查找到文件描述符对应的内核,socket结构后,会申请一块内存空间来保存链接成功的客户端状态,socket结构的一些参数,例如类型type操作方式ops等会继承服务器原来的值,例如原来服务器的类型为AF——INET则其操作模式仍然为af_inet.c文件中的各个函数,然后会查找到文件描述符表,获得一个新的结构对应的文件描述符。

在内核中使用一个消息结构msghdr用来存放所有的数据结构,其原型如下:

struct  msghdr{

       void *msg_name; //socket名称

      int msg_namelen; //socket名称的长度

       struct iovec* msg_iov; //向量,存放数据

       __kernel_size_t msg_iovlen;//向量数量

      void *msg_control;

      __kernel_size_t msg_controllen;//msg_control的数量

      unsigned msg_flags;      //消息选项

};

对于AF——INET 族,recvfrom对应于udp_recvmsg()函数,其实现在文件af_inet.c 中,

1接收数据报数据,。在接收的时候根据设置超时来确定是否要一直等待。

2计算复制出的数据长度,当街收到的数据长度比用户缓冲区的长度大时。设置MSG——MSG_TRUNC标志方便下次的复制

3将数据复制到用户缓冲区空间中。

4复制发送方的地址和协议族

5根据消息结构的标志设置,接收其他的信息,

6销毁数据报缓冲区对应的变量。

您可能感兴趣的与本文相关的镜像

Qwen-Image-Edit-2509

Qwen-Image-Edit-2509

图片编辑
Qwen

Qwen-Image-Edit-2509 是阿里巴巴通义千问团队于2025年9月发布的最新图像编辑AI模型,主要支持多图编辑,包括“人物+人物”、“人物+商品”等组合玩法

阅读下面代码:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#include <arpa/inet.h>#include <unistd.h>#include <signal.h>#include <stdint.h>#include <limits.h>// 统计数据结构typedef struct { size_t total_packets; // 接收包总数 size_t total_data; // 总数据字节数 size_t min_data; // 最小数据大小 size_t max_data; // 最大数据大小 size_t size_counts[1024]; // 各尺寸频次统计} PingStats;volatile sig_atomic_t running = 1;PingStats stats = {0, 0, SIZE_MAX, 0, {0}};// 信号处理函数 (Ctrl+C退出)void handle_signal(int sig) { running = 0;}// ICMP校验和计算 (RFC 1071)uint16_t checksum(void *b, int len) { uint16_t *buf = b; uint32_t sum = 0; for (sum = 0; len > 1; len -= 2) sum += *buf++; if (len == 1) sum += *(uint8_t*)buf; sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); return ~sum;}// 更新统计信息void update_stats(size_t data_size) { stats.total_packets++; stats.total_data += data_size; if (data_size < stats.min_data) stats.min_data = data_size; if (data_size > stats.max_data) stats.max_data = data_size; if (data_size < sizeof(stats.size_counts)/sizeof(stats.size_counts[0])) stats.size_counts[data_size]++;}// 打印统计结果void print_stats() { printf("\n╔══════════════════════════════════╗"); printf("\n║ ICMP PING DATA STATISTICS "); printf("\n╠══════════════════════╦════════════╣"); printf("\n║ Total Packets %-10zu ", stats.total_packets); printf("\n║ Total Data Received %-10zu ║", stats.total_data); printf("\n║ Min Data Size ║ %-10zu ", stats.min_data); printf("\n║ Max Data Size %-10zu ║", stats.max_data); printf("\n║ Avg Data Size ║ %-10.2f ", (double)stats.total_data / stats.total_packets); printf("\n╚══════════════════════╩════════════╝\n"); // 打印常见尺寸分布 printf("\n[ Size Distribution ]"); for (int i = 0; i < sizeof(stats.size_counts)/sizeof(stats.size_counts[0]); i++) { if (stats.size_counts[i] > 0) { printf("\n%4d bytes: %zu packets", i, stats.size_counts[i]); } } printf("\n");}int main() { // 注册信号处理 signal(SIGINT, handle_signal); // 创建原始套接字 int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sock < 0) { perror("socket"); exit(EXIT_FAILURE); } printf("[*] ICMP sniffer started. Press Ctrl+C to stop and view stats\n"); // 接收缓冲区 char buffer[2048]; struct sockaddr_in sender_addr; socklen_t addr_len = sizeof(sender_addr); while (running) { // 接收数据包 ssize_t packet_len = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&sender_addr, &addr_len); if (packet_len <= 0) continue; // 解析IP头部 struct iphdr *ip_hdr = (struct iphdr*)buffer; // 跳过非ICMP协议 if (ip_hdr->protocol != IPPROTO_ICMP) continue; int ip_hdr_len = ip_hdr->ihl * 4; // 计算IP头长度 // 指向ICMP报文 struct icmphdr *icmp_hdr = (struct icmphdr*)(buffer + ip_hdr_len); ssize_t icmp_len = packet_len - ip_hdr_len; // 只处理Echo Reply包 (类型0) if (icmp_hdr->type != ICMP_ECHOREPLY) continue; // 验证校验和 (可选) uint16_t recv_checksum = icmp_hdr->checksum; icmp_hdr->checksum = 0; if (checksum(icmp_hdr, icmp_len) != recv_checksum) { printf("[!] Invalid ICMP checksum\n"); continue; } // 计算数据部分大小 size_t data_size = icmp_len - sizeof(struct icmphdr); printf("Received %zu bytes from %s\n", data_size, inet_ntoa(sender_addr.sin_addr)); // 更新统计 update_stats(data_size); } // 打印最终统计 print_stats(); close(sock); return 0;}按下CTRL + C时没有反应
最新发布
08-08
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值