西安市阎良区建设局网站,个人网站可以做商业吗,wordpress搭建门户,蜂网站开发前言 上一章我们用W6100-EVB-PICO开发板做TCP 客户端连接服务器进行数据回环测试#xff0c;那么本章将用开发板做TCP服务器来进行数据回环测试。
TCP是什么#xff1f;什么是TCP Server#xff1f;能干什么#xff1f; TCP (Transmission Control Protocol) 是一种面向连…前言 上一章我们用W6100-EVB-PICO开发板做TCP 客户端连接服务器进行数据回环测试那么本章将用开发板做TCP服务器来进行数据回环测试。
TCP是什么什么是TCP Server能干什么 TCP (Transmission Control Protocol) 是一种面向连接的、可靠的、基于字节流的传输协议用于在计算机网络上传输数据。TCP Server是指TCP网络服务的服务器端连接用于接收客户端的连接请求并建立连接实现网络数据的交互。 TCP Server的主要作用是监听客户端的连接请求并建立与管理连接实现数据的可靠传输。通过TCPServer多个客户端可以同时与服务器建立连接实现数据的多点传输。 在TCP Server中服务器程序需要指定监听的端口号并使用TCP协议与客户端建立连接。一旦有客户端连接进来服务器程序就会为每个客户端建立一个单独的连接并通过数据流对象 (NetworkStream) 与客广端进行数据交互。 因此TCP Server可以帮助设备实现多点数据交互是设备联网通信的重要方式之一。在工业自动化、物联网、智能家居等应用中TCP Server被广泛使用。
连接方式
使开发板和我们的电脑处于同一网段
开发板设备通过交叉线直连主机PC 开发板和主机都接在路由器LAN口
测试工具
网络调试工具任意wireshark抓包工具
回环测试
1.相关代码
如下所示tcp服务端的回环测试函数需要我们传入三个参数socket端口号、收发数据的缓存和端口与做tcp客户端实现思路一样可参考上一章内容即通过Switch状态机轮询socket状态进行相应处理不同的是在初始化socket端口后不再是连接服务器而是开启端口监听。
因为W6100这款以太网芯片支持IPv6因此在回环模式上有着不同选择相应地处理上也会根据模式分别进行处理这里选择IPv4模式进行回环测试。
int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port, uint8_t loopback_mode)
{int32_t ret;datasize_t sentsize0;int8_t status,inter;uint8_t tmp 0;datasize_t received_size;uint8_t arg_tmp8;uint8_t* mode_msg;uint8_t dip[16];uint16_t dport;if(loopback_mode AS_IPV4){mode_msg msg_v4;}else if(loopback_mode AS_IPV6){mode_msg msg_v6;}else{mode_msg msg_dual;}#ifdef _LOOPBACK_DEBUG_uint8_t dst_ip[16], ext_status;uint16_t dst_port;#endifgetsockopt(sn, SO_STATUS, status);switch(status){case SOCK_ESTABLISHED :ctlsocket(sn,CS_GET_INTERRUPT,inter);if(inter Sn_IR_CON){#ifdef _LOOPBACK_DEBUG_getsockopt(sn,SO_DESTIP,dst_ip);getsockopt(sn,SO_EXTSTATUS, ext_status);if(ext_status TCPSOCK_MODE){//IPv6printf(%d:Peer IP : %04X:%04X, sn, ((uint16_t)dst_ip[0] 8) | ((uint16_t)dst_ip[1]),((uint16_t)dst_ip[2] 8) | ((uint16_t)dst_ip[3]));printf(:%04X:%04X, ((uint16_t)dst_ip[4] 8) | ((uint16_t)dst_ip[5]),((uint16_t)dst_ip[6] 8) | ((uint16_t)dst_ip[7]));printf(:%04X:%04X, ((uint16_t)dst_ip[8] 8) | ((uint16_t)dst_ip[9]),((uint16_t)dst_ip[10] 8) | ((uint16_t)dst_ip[11]));printf(:%04X:%04X, , ((uint16_t)dst_ip[12] 8) | ((uint16_t)dst_ip[13]),((uint16_t)dst_ip[14] 8) | ((uint16_t)dst_ip[15]));}else{//IPv4//getSn_DIPR(sn,dst_ip);printf(%d:Peer IP : %.3d.%.3d.%.3d.%.3d, ,sn, dst_ip[0], dst_ip[1], dst_ip[2], dst_ip[3]);}getsockopt(sn,SO_DESTPORT,dst_port);printf(Peer Port : %d\r\n, dst_port);#endifarg_tmp8 Sn_IR_CON;ctlsocket(sn,CS_CLR_INTERRUPT,arg_tmp8);}getsockopt(sn,SO_RECVBUF,received_size);if(received_size 0){if(received_size DATA_BUF_SIZE) received_size DATA_BUF_SIZE;ret recv(sn, buf, received_size);getsockopt(sn,SO_DESTIP,dip);getsockopt(sn,SO_DESTPORT,dport);printf(from the client with ip [%d.%d.%d.%d] - port [%d].\n,dip[0],dip[1],dip[2],dip[3],dport);printf(recv: %s,buf);if(ret 0) return ret; // check SOCKERR_BUSY SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY.received_size (uint16_t) ret;sentsize 0;while(received_size ! sentsize){ret send(sn, bufsentsize, received_size-sentsize);if(ret 0){close(sn);return ret;}sentsize ret; // Dont care SOCKERR_BUSY, because it is zero.}}break;case SOCK_CLOSE_WAIT :#ifdef _LOOPBACK_DEBUG_printf(%d:CloseWait\r\n,sn);#endifgetsockopt(sn, SO_RECVBUF, received_size);if(received_size 0) // Dont need to check SOCKERR_BUSY because it doesnt not occur.{if(received_size DATA_BUF_SIZE) received_size DATA_BUF_SIZE;ret recv(sn, buf, received_size);if(ret 0) return ret; // check SOCKERR_BUSY SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY.received_size (uint16_t) ret;sentsize 0;while(received_size ! sentsize){ret send(sn, bufsentsize, received_size-sentsize);if(ret 0){close(sn);return ret;}sentsize ret; // Dont care SOCKERR_BUSY, because it is zero.}}if((ret disconnect(sn)) ! SOCK_OK) return ret;#ifdef _LOOPBACK_DEBUG_printf(%d:Socket Closed\r\n, sn);#endifbreak;case SOCK_INIT :if( (ret listen(sn)) ! SOCK_OK) return ret;#ifdef _LOOPBACK_DEBUG_printf(%d:Listen, TCP server loopback, port [%d] as %s\r\n, sn, port, mode_msg);#endifprintf(%d:Listen, TCP server loopback, port [%d] as %s\r\n, sn, port, mode_msg);break;case SOCK_CLOSED:#ifdef _LOOPBACK_DEBUG_printf(%d:TCP server loopback start\r\n,sn);#endifswitch(loopback_mode){case AS_IPV4:tmp socket(sn, Sn_MR_TCP4, port, SOCK_IO_NONBLOCK);break;case AS_IPV6:tmp socket(sn, Sn_MR_TCP6, port, SOCK_IO_NONBLOCK);break;case AS_IPDUAL:tmp socket(sn, Sn_MR_TCPD, port, SOCK_IO_NONBLOCK);break;default:break;}if(tmp ! sn) /* reinitialize the socket */{#ifdef _LOOPBACK_DEBUG_printf(%d : Fail to create socket.\r\n,sn);#endifreturn SOCKERR_SOCKNUM;}#ifdef _LOOPBACK_DEBUG_printf(%d:Socket opened[%d]\r\n,sn, getSn_SR(sn));sock_state[sn] 1;#endifbreak;default:break;}return 1;
}
主函数就比较简单在此之前我们先声明socket端口号和所用最大的缓存大小不做分片处理默认为2KB然后初始化网络信息、目标IP地址和目标端口最后在while循环里调用loopback_tcps并传入相应参数即可。
注意这里的本地端口选择尽量避免使用特殊端口这里使用8080如下所示。
#define SOCKET_ID 0
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)void network_init(void);wiz_NetInfo net_info {.mac {0x00, 0x08, 0xdc, 0x16, 0xed, 0x2e},.ip {192, 168, 1, 10},.sn {255, 255, 255, 0},.gw {192, 168, 1, 1},.dns {8, 8, 8, 8},.ipmode NETINFO_STATIC_V4};
wiz_NetInfo get_info;
static uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE] {0,};
static uint16_t local_port 8080;int main()
{ stdio_init_all();sleep_ms(2000);network_init();while(true){loopback_tcps(SOCKET_ID, ethernet_buf, local_port, AS_IPV4);sleep_ms(500);}}void network_init(void)
{uint8_t temp;wizchip_initialize();printf(W6100 tcp server example.\r\n);sleep_ms(2000);/* Determine the network lock register status */if(!ctlwizchip(SYS_NET_LOCK, temp)){ printf(unlock.\n);NETUNLOCK();}wizchip_setnetinfo(net_info);print_net_info(get_info);sleep_ms(2000);
}
2.测试现象
我们编译烧录后打开串行监视器可以看到我们开发板通过串口回显的网络配置信息然后我们打开网络调试工具配置为TCP Client模式远程IP地址和远程端口为我们开发板的本地IP和端口然后点击连接并发送数据测试可以看到串口打印的信息我们电脑作为客户端成功连接并收到开发板回传的数据。 我们也可以在打开wireshark抓包工具输入命令ip.addr 192.168.1.10 and tcp过滤数据包IP地址改成自己电脑的IP或者开发板的IP地址即可我这里先关闭网络调试助手然后又打开接着发送0~9十个阿拉伯数字可以通过抓包工具十分清楚明了的看到具体交互过程如下图所示。 相关链接
本章相关例程链接https://gitee.com/wiznet-hk/example-of-w6100-evb-pico.gitwireshark抓包工具下载链接https://www.wireshark.org/download.html