首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

在网卡驱动里写下数据,是否要修改以太网帧头

2013-06-26 
在网卡驱动里写入数据,是否要修改以太网帧头?[解决办法]引用:你自定义的协议,每个通信帧竟然没有长度?一般

在网卡驱动里写入数据,是否要修改以太网帧头?

[解决办法]

引用:
你自定义的协议,每个通信帧竟然没有长度?

一般都有长度控制字节,这样才能帮助达到不粘包之类的功能啊。不然你怎么知道这帧数据有多长呢?这和变长不变长没关系的。

CRC怎么计算都有直接的函数的。就是验证是否通信帧是否由于通信问题导致错误。解释原理也很简单的。

他那个图是以太网的帧格式,以太网的帧是没有长度的,是通过以太网物理层的方式分帧的
参见http://en.wikipedia.org/wiki/Ethernet_frame#Preamble_and_start_frame_delimiter

Preamble and start frame delimiter [edit]
See also: Syncword
A frame starts with a 7-octet preamble and 1-octet start frame delimiter (SFD).[note 3] Prior to Fast Ethernet, the on-the-wire bit pattern for this portion of the frame is 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101011.[3] Since octets are transmitted least-significant bit first the corresponding hexadecimal representation is 0x55 0x55 0x55 0x55 0x55 0x55 0x55 0xD5.
PHY transceiver chips used for Fast Ethernet feature a 4-bit (one nibble) Media Independent Interface. Therefore the preamble will consist of 14 instances of 0x5, and the start frame delimiter 0x5 0xD. Gigabit Ethernet transceiver chips use a Gigabit Media Independent Interface that works 8-bits at a time, and 10 Gbit/s (XGMII) PHY works with 32-bits at a time.

很多抓包工具都是抓不到这些前导码的,网卡在物理层过滤掉了
[解决办法]
引用:

Quote: 引用:

长度必须要控制啊。主要是为了识别 \0 符号。
我找了些资料,发现一个说法:“32位CRC循环冗余校验对从"目标MAC地址"字段到"数据"字段的数据进行校验”如果是按照这个说法,那我修改了IP数据,那么以太网帧尾部 FSC 是必须改的了,那么以太网帧头部的那个 类型/长度 是否也是必须改的额???
那这个字段的校验时如何进行计算的额???求大虾指点下啦 哈哈



~~~此贴慢慢加分中啊~~~只求指点啊~~


类型应该不用改吧,因为你携带的就是ip数据包啊
如果是帧校验问题,那你第一次通信不可能正常啊
tcp包头那些个序号,你封包的时候填对没有?
[解决办法]

现在是一团乱了额····


你总结的没有错,但实际上这是两种不同协议,一种是标准以太网协议,一种是IEEE802.3mac协议

在网卡驱动里写下数据,是否要修改以太网帧头

以上图片来自TCP/IP协议卷1
[解决办法]
建议你看一下TCP/IP协议卷1,还有下个抓包工具来分析一下原因,推荐Wireshark
[解决办法]
引用:
类型应该不用改吧,因为你携带的就是ip数据包啊
如果是帧校验问题,那你第一次通信不可能正常啊
tcp包头那些个序号,你封包的时候填对没有?

我的TCP包头的序号我没有动它,
我的程序代功能是:TCP客户端(PC端)发送数据到TCP服务器(单片机端),TCP服务器就将这串数据返回去;(数据的第一位是‘C’这是我的条件判断)
如果按照正常的情况是这样的,在上层数据修改的话就直接将收到的数据发送就可以了:
if(uip_appdata[0]=='C')//假如收到的数据 第一个是‘C’就将这串数据返回去 
  {
 uip_send(&uip_appdata[0],uip_len);
}

这个是在上层的,如果我后面没有做其他动作是绝对可行的,而且没哟问题,执行了上面这个函数后,实际上要发送数据的话是转到网卡驱动进行发送数据的:dev_send()

void dev_send(void)
{if(uip_appdata[1]=='1') 
{
 // uip_len = uip_len+1;


//  uip_buf[uip_len-1]='9';
  lzm_tcpchksum();
         }

    enc28j60Packet_len(uip_len);
    enc28j60Packet_data(uip_len, uip_buf);
    enc28j60Packet_Send();
}


上面的代码表示,我在PC机TCP客户端向TCP服务器发送数据,第一个数据是'C'(这样才能够进入发送数据函数),第二个数据是 '1'那么就进行校验和计算 lzm_tcpchksum()(这里我重新计算 IP头校验和、TCP头校验和(TCP伪头部、TCP Head、还有数据)); 
1.如果if里面的那两个注释掉的语句没有执行,那么这个代码执行过程没有出错,不会卡住的。
2.但是假如我把那两个注释掉的语句去掉注释,执行代码后,就只能发送一次了。
3.如果我把那两句注释掉的代码 
        // uip_len = uip_len+1;
//  uip_buf[uip_len-1]='9';
改成 uip_appdata[1]='8';//就吧这个数据随便改一个,来验证我的校验和程序代码是否可行
那么这个代码执行过程没有出错,不会卡住的。

详细问题我只能描述这样了,不知道大家看懂了没有哦。那这个和TCP的 顺序号 填充有关系么?求指教啦~~~在网卡驱动里写下数据,是否要修改以太网帧头

lzm_tcpchksum这个的代码能贴上来吗?
[解决办法]
我理解uip_buf是IP层递交给链路层的数据,将作为以太网帧的数据被封装,uip_appdata为应用层数据,也就是TCP里面封装的数据,我发现你的代码只修改了uip_len这个值,但实际上应用层数据长度已经修改,那TCP头和IP头里的长度也应该做修改吧?

[解决办法]
  BUF->len[0] = (((uip_len-0x000e)) >> 8);
  BUF->len[1] = (((uip_len-0x000e)) & 0xff);

这里为什么要减去14呢?
[解决办法]

void dev_send(void)
{if(uip_appdata[1]=='1') 
{
 // uip_len = uip_len+1;
//  uip_buf[uip_len-1]='9';
  lzm_tcpchksum();
         }

    enc28j60Packet_len(uip_len);
    enc28j60Packet_data(uip_len, uip_buf);
    enc28j60Packet_Send();
}

这里的uip_buf是代表IP包还是以太网包
[解决办法]
uip_buf如果是以太网包,你怎么能够简单在以太网包后面加个‘9’呢?
uip_buf如果是IP包,那uip_len怎么在函数lzm_tcpchksum里又变成以太网包的长度?

[解决办法]
楼主你又不玩RawSocket,研究那么多干啥呢?
[解决办法]
明白你的意思,就是说其实uip_len是不包含以太网CRC的,以太网CRC是下面硬件自动计算并添加的。
对于校验和我不是很懂,也不多说,
你使用抓包工具来分析过吗
[解决办法]
引用:
Quote: 引用:

楼主你又不玩RawSocket,研究那么多干啥呢?
我是用单片机控制ENC28J60来实现单片机和PC机间通过网络进行通信,现在,由于单片机的RAM不大吧,而有时候需要发送一串叫大的数据比如说900字节的,那单片机只能分多次写入 网卡驱动,然后再一次性发送出去了。所以必须在网卡驱动层进行动手了,所以在发送长长的数据前,必须先构造 IP TCP的头 那些校验和什么的,然后将数据 多次写入网卡发送缓冲区,最后再一次发送,只有这样才可以实现啊。要不我也不想弄的这么麻烦了额。

使用tcp协议的话,你每次发送1字节,发送10次跟每次发送10字节,发送1次,效果不是一样的吗?所以的900字节其实可以分多次发送的吧,不会有任何影响吧?

热点排行