在Linux中使用原始套接字时,802.3标头长度始终为256

时间:2010-08-05 14:48:01

标签: c++ linux sockets raw-sockets

我有以下代码打开一个原始套接字并通过它发送。在发送函数中,我有一个跟踪语句,显示我的数据包的长度为21.但是,当我使用数据包嗅探器查看接收端的数据包时,我看到:

  1. 实际数据包长度为60。
  2. 长度(在802.3标题中给出)为256。
  3. 这些数字都不是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),应该没有用。

1 个答案:

答案 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。这是一个糟糕的垃圾。

发生了什么事?