memcpy(tcp_recbuf,(char*)&rxtx_buffer[tcp_loadpos],tcp
_reclen); // 范例1 TCP:Hello //准备返回数据
strcpy(tcp_sendbuf,\
strcat(tcp_sendbuf,tcp_recbuf); // 填充缓冲区 tcp_sendlen =
tcp_puts_data( rxtx_buffer,(BYTE*)tcp_sendbuf,0); // 服务器第3次发送,发送HTTP响应 发送FIN tcp_send_packet
( rxtx_buffer, // 发送缓冲区
(WORD_BYTES){dest_port}, // 目标端口
(WORD_BYTES){TCP_AVR_PORT_V}, // 源端口 // 标志 TCP_FLAG_ACK_V | TCP_FLAG_PSH_V |
TCP_FLAG_FIN_V, 0, // 不操作序号 0, // 不清除
确认号 0, // tcp_sendlen, // 负载长度 dest_mac, // 客户端MAC地址
dest_ip ); // 客户端IP地址 // 数据包被处理 return 1; } } // 返回0 代表数
据未被处理 return 0; } 4.实验
TCP报文的处理位于ARP、 IP、 ICMP和ICMP之后。获得TCP有效负载之后应存在在接收缓冲区中,进行合适的处理并返回结果。实验通过两个例子说明TCP的使用。
4.1 程序结构
[cpp] view plain copy void server_process ( void )
{ MAC_ADDR client_mac; IP_ADDR client_ip; WORD plen; // 获得新的IP报文 plen = enc28j60_packet_receive( (BYTE*)&rxtx_buffer,
MAX_RXTX_BUFFER ); if(plen==0) return; // 保存客服端的MAC地址 memcpy ( (BYTE*)&client_mac,
&rxtx_buffer[ ETH_SRC_MAC_P ],
sizeof( MAC_ADDR) ); // 检查该报文是不是ARP报文 if ( arp_packet_is_arp( rxtx_buffer,
(WORD_BYTES){ARP_OPCODE_REQUEST_V} ) ) { // 向客户端返回ARP报文
arp_send_reply ( (BYTE*)&rxtx_buffer,
(BYTE*)&client_mac ); return; } // 保存客服端的IP地址 memcpy
( (BYTE*)&client_ip, &rxtx_buffer[ IP_SRC_IP_P ], sizeof(IP_ADDR) ); // 检查该报文是否为IP报文 if ( ip_packet_is_ip ( (BYTE*)&rxtx_buffer ) == 0 ) { return; } // 如果是ICMP报文 向发起方返回数据 if ( icmp_send_reply ( (BYTE*)&rxtx_buffer, (BYTE*)&client_mac,
(BYTE*)&client_ip ) ) { return; } // 进行UDP处理 if (udp_receive ( (BYTE
*)&rxtx_buffer, (BYTE *)&client_mac, (BYTE *)&client_ip )) { return; } // 进行TCP处理 if (tcp_receive ( (BYTE
*)&rxtx_buffer, (BYTE *)&client_mac, (BYTE *)&client_ip ))
{ return; } }
4.2 TCP Hello
接收到TCP数据包之后,在负载数据之前加入Hello字符串,如果输入为xukai871105,则返回Hello xukai871105。通过网络调试助手查看返回结果。使用strcpy函数把Hello
复制到tcp_sendbuf数组中,接着使用strcat把tcp_recbuf中的字符串连接到tcp_sendbuf之后,最后调用tcp_send_packet
填充到发送缓冲区中。[cpp] view plain copy #if TCP_ECHO // 范例1 TCP:Hello //准备返回数据 strcpy(tcp_sendbuf,\
strcat(tcp_sendbuf,tcp_recbuf); // 填充缓冲区 tcp_sendlen =
tcp_puts_data(rxtx_buffer,(BYTE*)tcp_sendbuf,0); #endif
图1 TCP Hello实验结果 4.3 LED控制
验证TCP发送和接收之后,可以通过定义一组指令实现LED的控制。 led,x,y
x表示LED编号,取值范围为1或2 y表示LED状态,1为打开,2为关闭
具体代码如下:
[cpp] view plain copy #if TCP_LEDCTRL int match_count = 0; int led_index = 0; int led_status = 0; // 匹配led,x,y
match_count = sscanf(tcp_recbuf,\&led_index, &led_status); if(match_count == 2)
{ switch(led_index) { case 1:
led_status?BSP_LEDOn(1):BSP_LEDOff(1); tcp_sendlen = tcp_puts_data(rxtx_buffer, (BYTE*)\Control OK\\r\\n\ // dlength =
udp_puts_data(rxtx_buffer, (BYTE*)\ break; case 2:
led_status?BSP_LEDOn(2):BSP_LEDOff(2); tcp_sendlen = tcp_puts_data(rxtx_buffer, (BYTE*)\
Control OK\\r\\n\ break; default: tcp_sendlen =
tcp_puts_data(rxtx_buffer, (BYTE*)\ break; } } else { tcp_sendlen = tcp_puts_data(rxtx_buffer, (BYTE*)\0); } #endif 图2 TCP LED控制
5 总结和展望
本文为STM32NET学习笔记的最后一篇,以后将不再
更新。按照最原始的计划还有WEB部分的内容,但是若使用这样的框架尝试,那么整个系统会变得非常复杂且不可控制。如果想深入嵌入式网络,请查阅LwIP相关知识,或者尝试一下树莓派等linux开发板。