我正在 Linux/Debian 上使用 RAW 套接字,当我使用
write()
而不是 sendto()
时遇到问题:
struct sockaddr_ll socket_address;
/* Index of the network device */
socket_address.sll_ifindex = if_idx.ifr_ifindex;
/* Address length*/
socket_address.sll_halen = ETH_ALEN;
/* Destination MAC */
socket_address.sll_addr[0] = 0x00;
socket_address.sll_addr[1] = 0x11;
socket_address.sll_addr[2] = 0x22;
socket_address.sll_addr[3] = 0x33;
socket_address.sll_addr[4] = 0x44;
socket_address.sll_addr[5] = 0x55;
/* Send packet */
int b_written = 0;
if ( ( b_written = write(sockfd, sendbuf, tx_len,
(struct sockaddr*)&socket_address,
sizeof(struct sockaddr_ll))) < 0 )
/*
if ( ( b_written = sendto(sockfd, sendbuf, tx_len, 0,
(struct sockaddr*)&socket_address,
sizeof(struct sockaddr_ll))) < 0 )
*/
{
perror("Could not write socket...");
fprintf(stderr, "ERRNO = %d\n", errno);
exit(-1);
}
printf("Packet sent!, Bytes written = %d\n", b_written);
如果我使用
write
而不是 sendto
,我会收到以下错误:
No such device or address" (errno=6, which is defined as EXNIO).
使用
sendto
,我没有问题,数据包显示在tcpdump -nettti eth0 '(ether dst host 00:11:22:33:44:55)'
中。
根据
man sendto
,sendto
相当于不指定任何标志的写入。由于我用于 sendto
的标志字段是“0”,我猜这两个系统调用是等效的。
我可能做错了什么?这两个调用是等效的吗?
您必须
bind()
(参见手册)套接字地址,然后正确使用write()
(这意味着仅使用3参数)。
/* Send packet */
int b_written = 0;
if (bind(sockfd, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) == -1)
{
perror("bind");
exit(-1);
}
if ( ( b_written = write(sockfd, sendbuf, tx_len)) < 0 )
{
perror("Could not write socket...");
fprintf(stderr, "ERRNO = %d\n", errno);
exit(-1);
}
printf("Packet sent!, Bytes written = %d\n", b_written);
sendto() 调用只能在套接字处于连接状态时使用(以便知道预期的接收者)。 以下是 write 函数的原型,它有 3 个参数,而不是像 send() 函数那样有 5 个参数。
write(int fd, const void *buf, size_t count);
此消息是由对特殊文件的子设备的 I/O 产生的,该子设备要么不存在,要么超出设备的限制。因此,请检查您是否具有在要执行写入操作的位置写入的权限或访问权限。还要更改写入参数,因为它只能有三个参数。
来自手册页
int write(fd, buf, nbyte)
我希望这能解决问题。