我有以下代码打开一个原始套接字并通过它发送。在发送函数中,我有一个跟踪语句,显示我的数据包的长度为21.但是,当我使用数据包嗅探器查看接收端的数据包时,我看到:
这些数字都不是21,而且我正在与不喜欢这种差异的嵌入式设备进行通信。我已经用Google搜索了但我无法弄清楚如何让sendto()报告正确的长度。
bool EthernetSocket::_open(const char *ifname) {
_sd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_802_2));
_ifname = ifname;
_ifidx = Ethernet::GetInterface(ifname);
if(_sd < 0) {
perror("Failed to open socket");
_bOpened = false;
}
else {
_bOpened = true;
}
return _bOpened;
}
bool EthernetSocket::_send(const Buffer& txbuff, Address& addr) {
if(txbuff.Length() == 0)
return false;
if(_ifidx != -1)
addr.SetInterface(_ifidx);
printf("SEND: Length: %d\n", txbuff.Length());
if(sendto(_sd, txbuff.Data(), txbuff.Length(), 0, (struct sockaddr *) addr.Component(), (socklen_t) addr.Size()) == -1) {
perror("Failed broadcast");
return false;
}
return true;
}
编辑:我发现该字段被设置为sockaddr_ll结构中的sll_protocol字段。但为什么?将其设置为htons(ETH_P_802_2),应该没有用。
答案 0 :(得分:0)
我有部分答案。
将sll_protocol设置为htons(ETH_P_802_3)可以解决问题。我不确定为什么会这样,因为ETH_P_802_2和ETH_P_802_3应该表现得几乎相同 - 而且我能找到的所有相关内核源代码都支持我。
我通过recvfrom()使用协议ETH_P_802_2接收数据包,因此返回的地址的sll_protocol字段设置为ETH_P_802_2。这意味着要回复,我必须在接收数据后手动将字段设置为ETH_P_802_3。这是一个糟糕的垃圾。
发生了什么事?