W6100-EVB-PICO作为TCP Client 进行数据回环测试(五)

news2024/11/26 2:26:18

 前言

        上一章我们用W6100-EVB-PICO开发板通过DNS解析www.baidu.com(百度域名)成功得到其IP地址,那么本章我们将用我们的开发板作为客户端去连接服务器,并做数据回环测试:收到服务器发送的数据,并回传给服务器。

TCP是什么?什么是TCP Client? 能做什么?

        TCP (Transmission Control Protocol) 是一种面向连接的、可靠的、基于字节流的传输协议,用于在计算机网络上传输数据。TCP Client是指TCP网络服务的客户端连接,主动向服务器发起连接请求并建立连接,用于实现串口数据和服务器数据的交互,保证数据的可靠交换。TCP Clent通常用于设备与服务器之间的数据交互,是最常用的联网通信方式。
        TCP Client的主要作用是建立和管理与TCP服务器之间的连接,实现数据的可靠传输。通过TCP Client,设备可以向服务器发送数据并从服务器接收数据,从而实现设备与服务器之间的数据交互。
        在TCP Client中,客户端程序需要指定服务器的IP地址和端口号,并使用TCP协议与服务器建立连接。一旦连接建立成功,客户端程序就可以通过数据流对象 (NetworkStream) 与服务器进行数据交互。
        因此,TCP Client可以帮助设备实现与服务器之间的可靠数据交换,是设备联网通信的重要方式之一。在工业自动化、物联网、智能家居等应用中,TCP Client被广泛使用。

连接方式

使开发板和我们的电脑处于同一网段:

  • 开发板(设备)通过交叉线直连主机(PC)
  •  开发板和主机都接在路由器LAN口

测试工具

  • 网络调试工具(任意)
  • wireshark抓包工具

回环测试

1. 相关代码

 如下所示,我们可以看到应用实例里面loopback_tcpc的具体实现,我们需要传入五个参数:socket端口号、收发缓存、目的IP地址、目的端口号和回环模式;函数里面用一个Switch状态机,对socket端口状态轮询并进行相应的处理,处于连接状态就判断是否收到数据,如果有就获取数据大小,并做回传处理,回传失败就关闭端口;处于关闭状态就跑tcp协议并打开端口;处于初始化状态就连接服务器;处于等待关闭状态就断开连接。

值得一提的是W6100这款以太网芯片支持IPv6,因此在回环模式上有着不同选择,相应地处理上也会根据模式分别进行处理,这里选择IPv4模式进行回环测试。

int32_t loopback_tcpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport, uint8_t loopback_mode)
{

    int32_t ret; // return value for SOCK_ERRORs
    datasize_t sentsize=0;
    uint8_t status,inter,addr_len;
    datasize_t received_size;
    uint8_t tmp = 0;
    uint8_t arg_tmp8;
    wiz_IPAddress destinfo;


    // Socket Status Transitions
    // Check the W6100 Socket n status register (Sn_SR, The 'Sn_SR' controlled by Sn_CR command or Packet send/recv status)
    getsockopt(sn,SO_STATUS,&status);
    switch(status)
    {
    case SOCK_ESTABLISHED :
        ctlsocket(sn,CS_GET_INTERRUPT,&inter);
        if(inter & Sn_IR_CON)	// Socket n interrupt register mask; TCP CON interrupt = connection with peer is successful
        {
            #ifdef _LOOPBACK_DEBUG_
                printf("%d:Connected to - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
            #endif
            arg_tmp8 = Sn_IR_CON;
            ctlsocket(sn,CS_CLR_INTERRUPT,&arg_tmp8);// this interrupt should be write the bit cleared to '1'
        }

        //
        // Data Transaction Parts; Handle the [data receive and send] process
        //
        getsockopt(sn, SO_RECVBUF, &received_size);

        if(received_size > 0) // Sn_RX_RSR: Socket n Received Size Register, Receiving data length
        {
            if(received_size > DATA_BUF_SIZE) received_size = DATA_BUF_SIZE; // DATA_BUF_SIZE means user defined buffer size (array)
            ret = recv(sn, buf, received_size); // Data Receive process (H/W Rx socket buffer -> User's buffer)

            if(ret <= 0) return ret; // If the received data length <= 0, receive failed and process end
            received_size = (uint16_t) ret;
            sentsize = 0;

            // Data sentsize control
            while(received_size != sentsize)
            {
                ret = send(sn, buf+sentsize, received_size-sentsize); // Data send process (User's buffer -> Destination through H/W Tx socket buffer)
                if(ret < 0) // Send Error occurred (sent data length < 0)
                {
                    close(sn); // socket close
                    return ret;
                }
                sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
            }
        }
        //
        break;

    case SOCK_CLOSE_WAIT :
        #ifdef _LOOPBACK_DEBUG_
            printf("%d:CloseWait\r\n",sn);
        #endif
        getsockopt(sn, SO_RECVBUF, &received_size);

        if((received_size = getSn_RX_RSR(sn)) > 0) // Sn_RX_RSR: Socket n Received Size Register, Receiving data length
        {
            if(received_size > DATA_BUF_SIZE) received_size = DATA_BUF_SIZE; // DATA_BUF_SIZE means user defined buffer size (array)
            ret = recv(sn, buf, received_size); // Data Receive process (H/W Rx socket buffer -> User's buffer)

            if(ret <= 0) return ret; // If the received data length <= 0, receive failed and process end
            received_size = (uint16_t) ret;
            sentsize = 0;

            // Data sentsize control
            while(received_size != sentsize)
            {
                ret = send(sn, buf+sentsize, received_size-sentsize); // Data send process (User's buffer -> Destination through H/W Tx socket buffer)
                if(ret < 0) // Send Error occurred (sent data length < 0)
                {
                    close(sn); // socket close
                    return ret;
                }
                sentsize += ret; // Don't 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);
            #endif
        break;

    case SOCK_INIT :
        #ifdef _LOOPBACK_DEBUG_
            if(loopback_mode == AS_IPV4)
                printf("%d:Try to connect to the %d.%d.%d.%d, %d\r\n", sn, destip[0], destip[1], destip[2], destip[3], destport);
            else if(loopback_mode == AS_IPV6)
            {
                printf("%d:Try to connect to the %04X:%04X", sn, ((uint16_t)destip[0] << 8) | ((uint16_t)destip[1]),
                    ((uint16_t)destip[2] << 8) | ((uint16_t)destip[3]));
                printf(":%04X:%04X", ((uint16_t)destip[4] << 8) | ((uint16_t)destip[5]),
                    ((uint16_t)destip[6] << 8) | ((uint16_t)destip[7]));
                printf(":%04X:%04X", ((uint16_t)destip[8] << 8) | ((uint16_t)destip[9]),
                    ((uint16_t)destip[10] << 8) | ((uint16_t)destip[11]));
                printf(":%04X:%04X,", ((uint16_t)destip[12] << 8) | ((uint16_t)destip[13]),
                    ((uint16_t)destip[14] << 8) | ((uint16_t)destip[15]));
                printf("%d\r\n", destport);
            }
        #endif

        if(loopback_mode == AS_IPV4)
          ret = connect(sn, destip, destport, 4); /* Try to connect to TCP server(Socket, DestIP, DestPort) */
        else if(loopback_mode == AS_IPV6)
          ret = connect(sn, destip, destport, 16); /* Try to connect to TCP server(Socket, DestIP, DestPort) */

        printf("SOCK Status: %d\r\n", ret);

        if( ret != SOCK_OK) return ret;	//	Try to TCP connect to the TCP server (destination)
        break;

    case SOCK_CLOSED:
        switch(loopback_mode)
        {
        case AS_IPV4:
            tmp = socket(sn, Sn_MR_TCP4, any_port++, SOCK_IO_NONBLOCK);
            break;
        case AS_IPV6:
            tmp = socket(sn, Sn_MR_TCP6, any_port++, SOCK_IO_NONBLOCK);
            break;
        case AS_IPDUAL:
            tmp = socket(sn, Sn_MR_TCPD, any_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);
            #endif
            return SOCKERR_SOCKNUM;
        }
        printf("%d:Socket opened[%d]\r\n",sn, getSn_SR(sn));
        sock_state[sn] = 1;

        break;
    default:
        break;
    }
    return 1;
}

 主函数就比较简单,在此之前我们先声明socket端口号和所用最大的缓存大小,不做分片处理默认为2KB;然后初始化网络信息、目标IP地址和目标端口,最后在while循环里调用loopback_tcpc并传入相应参数即可。

注意:这里的目的IP地址设置为我们的电脑IP地址,因为我们要让电脑端作为服务器,使用网络调试助手进行数据回环测试;另外目标端口选择尽量避免使用特殊端口,这里使用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 uint8_t des_ip[4] = {192, 168, 1, 2};
static uint16_t des_port = 8080;

int main()                                                          
{   
    stdio_init_all();
    sleep_ms(2000);
    network_init();

    while(true)
    {
        loopback_tcpc(SOCKET_ID, ethernet_buf, des_ip, des_port, AS_IPV4);
        sleep_ms(500);
    }
    

}

void network_init(void)
{
    uint8_t temp;
    wizchip_initialize();
     printf("W6100 dns test 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.测试现象

我们编译烧录后,打开串行监视器,可以看到,配置相关信息后,尝试连接我们初始化设置的目的IP(电脑IP),然后我们在电脑上打开网络调试助手,选择tcp服务器模式,IP选择电脑的本机IP(一般默认即为电脑IP),端口号写8080(跟我们在开发板配置的信息一致,不然监听不到),配置完成打开后,可以看到客户端上线提示,尝试发送数据,可以看到成功回传。

 

 我们也可以在打开wireshark抓包工具,输入命令<ip.addr == 192.168.1.10 and tcp>过滤数据包(IP地址改成自己电脑的,也即开发板设置的目标IP地址);我这里先关闭网络调试助手,然后又打开,接着发送0~9十个阿拉伯数字,可以通过抓包工具十分清楚明了的看到具体交互过程,如下图所示。

 相关链接:

本章相应例程链接https://gitee.com/wiznet-hk/example-of-w6100-evb-pico.gitwireshark抓包工具下载链接https://www.wireshark.org/download.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/848095.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【BI系统】选型常见问题解答二

本文主要总结BI系统选型过程中遇见的常见问题&#xff0c;并针对性做出回答&#xff0c;希望能为即将选型&#xff0c;或正在选型BI系统的企业用户们提供一个快速了解通道。 有针对金蝶云星空的BI方案吗&#xff1f;能起到怎样的作用&#xff1f; 答&#xff1a;奥威BI系统拥…

Windows新版文件资源管理器经常在后台弹出的临时解决方案

禁用组策略自动刷新 运行gpedit.msc找到计算机配置->管理模板->系统->组策略找到 “关闭组策略的后台刷新”启用 参考 https://answers.microsoft.com/en-us/windows/forum/all/windows-11-most-recently-opened-explorer-window/26e097bd-1eba-4462-99bd-61597b5…

网络编程 tcp udp http编程流程 网络基础知识

讲解 网络基础知识网络编程tcp编程流程图示理解bind和accept函数理解监视套接字和链接套接字理解linux和window下的编程实现tcp特点 udp编程流程图示理解udp特点 http编程流程图示理解编程实现-网站服务器 网络基础知识 OSI分层&#xff1a;应用层 表示层 会话层 传输层 网络层…

相关搜索量激增10000%!“芭比周边”产品火爆亚马逊!

据外媒报道&#xff0c;芭比娃娃是今年夏天最热的话题。今年7月份&#xff0c;“芭比娃娃”是亚马逊上搜索最多的词。第二季度&#xff0c;Shopify上的芭比娃娃销量激增了56%。知名玩具制造商美泰&#xff08;Mattel&#xff09;预计&#xff0c;受电影的推动&#xff0c;在未来…

echarts没有数据时也显示y轴刻度

一般如果没有数据&#xff0c;echarts的y轴刻度会隐藏&#xff0c;如果想让y轴刻度显示&#xff0c;需要设置yAxis的 min、max属性&#xff1a; 但是max数据不能写死&#xff0c;如果写死的话&#xff0c;万一实际数据量过大的话&#xff0c;会溢出echarts&#xff0c;所以做个…

找短视频BGM、音效素材,有这6个网站就够了。

很多从事自媒体的朋友不知道去哪里找免费的音效和好听的BGM&#xff0c;作为网站收藏家的我&#xff0c;本期就给大家分享6个视频剪辑必备的音效素材网站&#xff0c;有免费、付费、商用的&#xff0c;大家可以根据自己的需求进行选择&#xff0c;有需要的赶紧收藏起来吧&#…

Linux安装配置nginx+php搭建

Linux安装配置nginxphp搭建 文章目录 Linux安装配置nginxphp搭建1.nginx源码包编译环境和安装相应的依赖1.1 安装编译环境1.2 安装pcre库、zlib库和openssl库 2.安装nginx2.1 在[nginx官网](https://nginx.org/en/download.html)上获取源码包并进行下载2.2 进行解压编译 3.启动…

uboot详解

uboot入口 在PC机上引导程序一般由BIOS开始执行&#xff0c;然后读取硬盘中位于MBR(Main Boot Record&#xff0c;主引导记录)中的Bootloader(例如LILO或GRUB),并进一步引导操作系统的启动。然而在嵌入式系统中通常没有像BIOS那样的固件程序&#xff0c;因此整个系统的加载启动…

mybatis打印sql语句出现多余的limit关键字

1、事情起因 在项目中使用了PageHelper分页插件&#xff0c;由于需求特殊&#xff0c;需要自定义分页&#xff0c;代码编写完成后&#xff0c;事故出现了。 前端传参: {pageNum: 1,pageSize: 10, }已知表中数据10条&#xff0c;但是每次分页查询只有10条数据&#xff0c;排查…

第17章-Spring AOP经典应用场景

文章目录 一、日志处理二、事务控制三、参数校验四、自定义注解五、AOP 方法失效问题1. ApplicationContext2. AopContext3. 注入自身 六、附录1. 示例代码 AOP 提供了一种面向切面操作的扩展机制&#xff0c;通常这些操作是与业务无关的&#xff0c;在实际应用中&#xff0c;可…

5. C++类的封装

一、类的封装 封装的含义&#xff1a; 所有属性都是私有的&#xff0c;外部不能直接访问提供与属性相关的成员函数&#xff0c;间接访问属性 模板代码&#xff1a; #include <iostream> using namespace std;class Clock { private:int hour, minute, second; public…

《UNIX 传奇:历史与回忆》读后感

《UNIX 传奇&#xff1a;历史与回忆》 是 bwk&#xff08;Brian W. Kernighan&#xff09;2019 年的新作&#xff0c;回忆了 UNIX 在大半个世纪的风雨历程&#xff0c;是一本引人入胜的书籍。通过对 UNIX 操作系统的历史和发展进行详细的叙述和回顾&#xff0c;让我对这个操作系…

浅析基于安防监控EasyCVR视频汇聚融合技术的运输管理系统

一、项目背景 近年来&#xff0c;随着物流行业迅速发展&#xff0c;物流运输费用高、运输过程不透明、货损货差率高、供应链协同能力差等问题不断涌现&#xff0c;严重影响了物流作业效率&#xff0c;市场对于运输管理数字化需求愈发迫切。当前运输行业存在的难题如下&#xf…

Java volatile关键字分析

每个线程创建时&#xff0c;JVM会为其创建一份私有的工作内存&#xff08;栈空间&#xff09;&#xff0c;不同线程的工作内存之间不能直接互相访问 JMM规定所有的变量都存在主内存&#xff0c;主内存是共享内存区域&#xff0c;所有线程都可以访问 线程对变量进行读写&#xf…

计算机组成原理-笔记-第三章

目录 计算机组成原理——第三章——存储系统 1、基本概念 &#xff08;1&#xff09;分类 &#xff08;2&#xff09;总结 2、主存储器&#xff08;基本原理&#xff09; &#xff08;1&#xff09;译码器、控制电路、存储单元 &#xff08;容量计算&#xff09; &…

匈牙利算法详解

匈牙利算法(Hungarian Algorithm)是一种组合优化算法(combinatorial optimization algorithm)&#xff0c;用于求解指派问题(assignment problem)&#xff0c;算法时间复杂度为O(N^3)。Harold Kuhn发表于1955年&#xff0c;由于该算法基于两位匈牙利数学家的早期研究成果&#…

数字IC流片经历有多重要?怎样才能有流片机会?

都说拥有流片经验可以显示你在实际项目中的实践能力和对整个设计流程的了解程度&#xff0c;流片经历的重要性不言而喻。 什么是芯片流片 像流水线一样通过一系列工艺步骤制造芯片&#xff0c;这就是流片。在芯片制造过程中一般有两段时间可以叫作流片。 流片&#xff1a;英…

分布式测试插件 pytest-xdist 使用详解

目录 使用背景&#xff1a; 使用前提&#xff1a; 使用快速入门&#xff1a; 使用小结&#xff1a; 使用背景&#xff1a; 大型测试套件&#xff1a;当你的测试套件非常庞大&#xff0c;包含了大量的测试用例时&#xff0c;pytest-xdist可以通过并行执行来加速整体的测试过…

Unity数字可视化学校_昼夜(二)

1、时间设置&#xff1a; 2、新建夜晚 3、新建侧置球&#xff08;BOX&#xff09;,测试灯光强度 降低亮度 色调&#xff1a;冷色调 4、自发光 新建shader 灯光控制 道路线&#xff1a; 建筑&#xff1a; 夜晚加灯光&#xff1a; 玻璃&#xff1a; 加大灯光数量&#xff1a; 边缘…

深入理解负载均衡原理及算法

1. 前言 在互联网早期,网络还不是很发达,上网用户少,流量相对较小,系统架构以单体架构为主。但如今在互联网发达的今天,流量请求动辄百亿、甚至上千亿,单台服务器或者实例已完全不能满足需求,这就有了集群。不论是为了实现高可用还是高性能,都需要用到多台机器来扩展服…