TCP 协议在 STM32 上的移植(3)

2019-01-27 10:21

rxtx_buffer[ TCP_CHECKSUM_H_P ] = ck.byte.high; rxtx_buffer[ TCP_CHECKSUM_L_P ] = ck.byte.low; // 通过enc28j60发送数据 enc28j60_packet_send ( rxtx_buffer,

ETH_HEADER_LEN+IP_HEADER_LEN+TCP_HEADER_LEN+dlength ); }

3.2 TCP负载长度查询

TCP负载长度查询需要根据IP报文中数据包的总大小和TCP报文中的数据偏移量决定,并需要注意TCP的数据偏移量的单位为双字,即4个字节长度。 [cpp] view plain copy WORD tcp_get_dlength ( BYTE *rxtx_buffer )

{ int dlength, hlength; // 获得IP报文总大小 dlength = ( rxtx_buffer[ IP_TOTLEN_H_P ] <<8 ) | ( rxtx_buffer[ IP_TOTLEN_L_P ] ); // 除去IP报文头部大小 dlength -= IP_HEADER_LEN; // 获得TCP报文数据偏移量 单位为字,需要X4 hlength = (rxtx_buffer[ TCP_HEADER_LEN_P ]>>4) * 4; // 除去TCP报文数据偏移量 dlength -= hlength; if ( dlength <= 0 ) dlength=0; return ((WORD)dlength); }

3.3 TCP负载位置查询 [cpp] view plain copy BYTE tcp_get_hlength ( BYTE *rxtx_buffer ) { // 获得TCP报文数据偏移量 单位为字,需要X4 return ((rxtx_buffer[ TCP_HEADER_LEN_P ]>>4) * 4); // generate len in bytes; } 3.4 TCP负载填充

TCP的负载数据填充和UDP的负载数据填充相似。 [cpp] view plain copy WORD tcp_puts_data ( BYTE *rxtx_buffer, BYTE *data, WORD offset ) { while( *data )

{ rxtx_buffer[ TCP_DATA_P + offset ] = *data++; offset++; } return offset; }

3.5 TCP数据包处理

TCP数据包的处理代码较多,该函数会返回1或0,1代表以太网接收缓冲区的数据被处理,而0代表数据尚未被处理。TCP数据包的处理包含具体的应用实现,该部分出现在服务器端第二次返回ACK之后,具体的代码请结合范例和上文的TCP连接部分。

[cpp] view plain copy BYTE tcp_receive ( BYTE *rxtx_buffer, BYTE *dest_mac, BYTE *dest_ip ) { WORD

tcp_reclen, tcp_sendlen , dest_port; // 获得目标端口号 即客户端端口号 dest_port =

(rxtx_buffer[TCP_SRC_PORT_H_P]<<8)|rxtx_buffer[TCP_SRC_PORT_L_P]; // 匹配TCP协议类型,匹配端口 if ( rxtx_buffer [ IP_PROTO_P ] == IP_PROTO_TCP_V && \\ rxtx_buffer

[ TCP_DST_PORT_H_P ] == TCP_AVR_PORT_H_V && \\ rxtx_buffer

[ TCP_DST_PORT_L_P ] == TCP_AVR_PORT_L_V ) { // 服务器端第1次发送 收到SYN 返回SYN+ACK if ( (rxtx_buffer[ TCP_FLAGS_P ] & TCP_FLAG_SYN_V) ) { tcp_send_packet

( rxtx_buffer, // 发送缓冲区

(WORD_BYTES){dest_port}, // 目标端口号

(WORD_BYTES){TCP_AVR_PORT_V}, // 源端口号 TCP_FLAG_SYN_V|TCP_FLAG_ACK_V, // 标志位 同步位和应答位 1, // 初始化序号,只有在接收到SYN时使用 0, // 不清除确认号 1, //

确认号为上一个数据包的应答编号加1,SYN占用一个序号

0, // 负载长度 dest_mac, // 客户端MAC地址 dest_ip // 客户端IP地

址 ); return 1; } // 收到ACK报文 多种情况 if ( (rxtx_buffer [ TCP_FLAGS_P ] & TCP_FLAG_ACK_V) ) { // 获得TCP负载长度 tcp_reclen =

tcp_get_dlength( rxtx_buffer ); if ( tcp_reclen == 0 ) { // 服务器第4次发送,收到FIN,返回ACK // 主要是为了区别 建立连接时的最后一个ACK if ( (rxtx_buffer[TCP_FLAGS_P] & TCP_FLAG_FIN_V) ) { tcp_send_packet

( rxtx_buffer, // 发送缓冲区

(WORD_BYTES){dest_port}, // 目标端口

(WORD_BYTES){TCP_AVR_PORT_V}, // 源端口 TCP_FLAG_ACK_V, // 标志位 应答 0, // 不操作序号 0, // 不清楚确认号

1, // FIN占一个序号,在一个数据包的序号的基础上累加1

0, // 负载大小

dest_mac, // 客户端MAC地址 dest_ip // 客户端IP地

址 ); } return 1; } // 服务器第2次发送,返回ACK tcp_send_packet

( rxtx_buffer, // 发送缓冲区

(WORD_BYTES){dest_port}, // 目标端口号

(WORD_BYTES){TCP_AVR_PORT_V}, // 源端口号 TCP_FLAG_ACK_V, // 标志位 应答标志 0, // 不操作序号 0, // 不清除确认号 tcp_reclen, //

在上一个数据包的基础上累加tcp_reclen 0, // 负载长度 dest_mac, // 客户端MAC地址 dest_ip ); // 客户端IP地址 // 确定TCP负载位置 WORD tcp_loadpos = tcp_get_hlength( rxtx_buffer) + ETH_HEADER_LEN +

IP_HEADER_LEN; // 复制缓冲区数据


TCP 协议在 STM32 上的移植(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:第一个安全教育周内容

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: