C语言Raw sockets编程中connect操作是否属于冗余步骤?
结论
当你使用AF_PACKET族的SOCK_RAW套接字,且已经自行构造了包含完整二层头部的有效以太网帧时,connect()步骤完全冗余,可以直接省略。
你给出的示例流程:
int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); struct sockaddr_ll sll; /* populate sll with the target and interface info */ connect(sockfd, (struct sockaddr*)&sll, sizeof(sll)); write(sockfd, stuff, sizeof(stuff)); close(sockfd);
在stuff为完整以太网帧的场景下,可以简化为直接调用write/send发送,不需要提前connect。
相关核心知识点
1. AF_PACKET原始套接字的两种工作逻辑
AF_PACKET的SOCK_RAW类型套接字,内核处理发送请求时有两套逻辑:
- 自动填充二层头部:如果发送缓冲区只包含三层及以上 payload,内核会根据传入的地址信息(来自
connect绑定的sockaddr_ll,或者sendto传入的地址参数)自动构造以太网帧头部,再交给网卡发送。 - 直接透传完整帧:如果发送缓冲区已经包含完整的以太网帧头部,内核会跳过头部填充逻辑,直接将完整帧交给网卡发送,此时所有提前绑定的地址、接口参数都会被忽略,完全以你构造的帧内容为准。
2. connect的实际作用
connect对AF_PACKET套接字的唯一作用,是预先绑定固定的目标二层地址、发送网卡等参数,适合需要连续向同一个目标发送、且不想每次调用sendto都传地址参数的场景,仅在内核需要自动填充二层头部时生效。
3. 额外注意事项
- 运行该程序的进程需要持有
CAP_NET_RAW权限,否则无法创建AF_PACKET原始套接字,也无法发送自定义帧。 - 如果需要固定从指定网卡发送,不需要用
connect实现,可以调用setsockopt设置SO_BINDTODEVICE参数绑定网卡,开销更低逻辑也更清晰。 - 部分网卡或内核会校验以太网帧的校验和,如果自行构造的帧校验和无效会被丢弃,你可以选择自行计算校验和,也可以设置套接字参数让内核自动填充校验和。
内容的提问来源于stack exchange,提问作者Tretorn
相关产品推荐
相关产品推荐

