W6100-EVB-PICO 做TCP Server進行回環測試(六)

前言

????????上一章我們用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 sentsize=0;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, buf+sentsize, received_size-sentsize);if(ret < 0){close(sn);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);#endifgetsockopt(sn, SO_RECVBUF, &received_size);if(received_size > 0) // Don't need to check SOCKERR_BUSY because it doesn't 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, buf+sentsize, received_size-sentsize);if(ret < 0){close(sn);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);#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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/35457.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/35457.shtml
英文地址,請注明出處:http://en.pswp.cn/news/35457.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

zabbix監控安裝部署

目錄 一、環境 二、配置 1.配置yum源&#xff0c;這里用的清華的 2.過濾一下安裝包&#xff0c;查看依賴包 安裝依賴包 3.配置數據庫 開機自啟 創建數據庫 創建用戶 授權 導入數據到數據庫 查看zabbix數據庫有沒有表和數據 4.修改zabbix配置文件 1.修改zabbix配置…

去趨勢化一個心電圖信號、信號功率譜、低通IIR濾波器并平滑信號、對濾波器引起的延遲進行補償研究(Matlab代碼實現)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;歡迎來到本博客????&#x1f4a5;&#x1f4a5; &#x1f3c6;博主優勢&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客內容盡量做到思維縝密&#xff0c;邏輯清晰&#xff0c;為了方便讀者。 ??座右銘&a…

SPM實現framework自動管理和分發

一、前言 Swift Package Manager (SPM) 是蘋果官方提供的用于管理 Swift 項目的依賴關系和構建過程的工具。它是一個集成在 Swift 編程語言中的包管理器&#xff0c;用于解決在開發過程中管理和構建包依賴項的需求。 那么如何使用SPM管理和分發Objective C編寫的二進制庫呢&a…

HOT86-單詞拆分

leetcode原題鏈接&#xff1a;單詞拆分 題目描述 給你一個字符串 s 和一個字符串列表 wordDict 作為字典。請你判斷是否可以利用字典中出現的單詞拼接出 s 。注意&#xff1a;不要求字典中出現的單詞全部都使用&#xff0c;并且字典中的單詞可以重復使用。 示例 1&#xff1a…

不同路徑 II——力扣63

class Solution {public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int n=

一鍵登錄是如何在登錄方式中脫穎而出的?

首先&#xff0c;我們先了解一下登錄方式的演變過程&#xff0c;大致可以分為三個階段。分別是賬號密碼登錄、短信驗證碼登錄和一鍵登錄。 階段一&#xff1a;賬號密碼登錄 賬號密碼登錄是一種常見的用戶身份驗證方式&#xff0c;用戶需要輸入一個唯一的賬號和對應的密碼來登…

【APITable】教程:創建并運行一個自建小程序

1.進入APITable&#xff0c;在想要創建小程序的看板頁面點擊右上角的【小程序】&#xff0c;進入小程序編輯頁面。 2.創建一個新的小程序區。 點擊【 添加小程序】 點擊創建小程序&#xff0c;選擇模板&#xff0c;輸入名字。 3.確定后進入小程序部署引導頁面。 4.打開Xshell 7…

初識鴻蒙跨平臺開發框架ArkUI-X

HarmonyOS是一款面向萬物互聯時代的、全新的分布式操作系統。在傳統的單設備系統能力基礎上&#xff0c;HarmonyOS提出了基于同一套系統能力、適配多種終端形態的分布式理念&#xff0c;能夠支持手機、平板、智能穿戴、智慧屏、車機等多種終端設備&#xff0c;提供全場景&#…

99. for循環練習題-3種方式輸出0-9

【目錄】 文章目錄 99. for循環練習題-3種方式輸出0-91. for循環和while循環的區別2. 輸出 0~(n-1)的數字2.1 基礎代碼2.2 自定義函數代碼2.3 異常處理語句代碼 【正文】 99. for循環練習題-3種方式輸出0-9 1. for循環和while循環的區別 for循環和while循環都用于重復執行特定…

Linux一些常見的命令

1. 基礎命令 1. ls&#xff1a; 列出目錄內容。- 例如&#xff1a;ls -l 以長格式列出文件和目錄。2. cd&#xff1a; 切換工作目錄。- 例如&#xff1a;cd /home/user 進入 /home/user 目錄。3. pwd&#xff1a; 顯示當前工作目錄的路徑。4. mkdir&#xff1a; 創建新目錄。-…

flink-對齊和不對齊,精準一次和至少一次

精準一次怎么保證&#xff1f;可以設置為以下2個 對齊 當有一個barrier比較快時&#xff0c;輸入緩沖區阻塞&#xff0c;當另外一個barrier到來時&#xff0c;才進行備份&#xff0c;所以數據不會重復。優點&#xff1a;不會造成數據重復缺點&#xff1a;會造成數據積壓&#x…

ChatGPT Plus和ChatGPT對比

模型規模更大&#xff0c;參數數量超過6萬億&#xff0c;比ChatGPT大很多訓練數據更豐富&#xff0c;包括不同語言、領域和類型的數據語言理解和生成能力更強&#xff0c;能夠更準確地理解和生成文本可解釋性和可控性更好&#xff0c;支持更多的調參和控制參數&#xff0c;生成…

uni-app和springboot完成前端后端對稱加密解密流程

概述 使用對稱加密的方式實現。前端基于crypto-js。uni-app框架中是在uni.request的基礎上&#xff0c;在攔截器中處理的。springboot在Filter中完成解密工作。 uni-app 項目中引入crypto-js。 npm install crypto-js加密方法 const SECRET_KEY CryptoJS.enc.Utf8.parse(…

最強自動化測試框架Playwright(20)- iframe

一個頁面可以附加一個或多個 Frame 對象。每個頁面都有一個主框架&#xff0c;并且假定頁面級交互&#xff08;如&#xff09;在主框架中運行。click frame_locator 使用 iframe 時&#xff0c;可以創建一個框架定位器&#xff0c;該定位器將進入 iframe 并允許選擇該 iframe…

idea模板的使用(配置xml文件模板)

1. 問題的引出 我們在日常項目中可以發現&#xff0c;sql映射文件和mybatis主配置文件&#xff0c;以及application.yml文件中有很多固定不變的內容&#xff0c;為了方面使用&#xff0c;所以可以把這些xml文件設置為模板 2. 創建模板的步驟 按照圖片一步一步進行即可 點擊…

gcc編譯選項之預處理向源碼傳參和條件編譯

一、是什么? 預處理:是指在進行加工前準備工作. gcc 選項 文件名字 二、使用步驟 1.向源碼傳參 gcc -save-temps -DSENSOR_TYPE=SONY_IMX477_MIPI_8M_30FPS_12BIT hello.c -o hello 代碼如下(示例): #include <stdio.h> #include <stdlib.h>typedef enum …

acwing 平衡括號字符串 貪心 括號序列

&#x1f468;?&#x1f3eb; 平衡括號字符串 給定一個字符串 s s s&#xff0c;該字符串的每個字符都是 (、) 或 # 之一。 你的任務是將 s s s 中的每個 # 變換為一個或多個 )&#xff0c;從而得到一個平衡括號字符串。 不同 # 變換的 ) 的數量可以不同。 請你輸出為了…

數據容器——元組(tuple)

1、元組與列表的不同點 列表是可以修改的。如果想要傳遞的信息&#xff0c;不被算改&#xff0c;列表就不合適了。 元組同列表一樣&#xff0c;都是可以封裝多個、不同類型的元素在內。 但最大的不同點在于&#xff1a;元組一旦定義完成&#xff0c;就不可修改 所以&#xff…

2023河南萌新聯賽第(五)場:鄭州輕工業大學 --01分數規劃

題目描述 給定一個字符串 s&#xff0c;僅含 0, 1, ? 三種字符&#xff0c;你必須將所有 ? 替換為 1 或 0 。 定義 s 的美好值為將所有?進行替換后&#xff0c;s的最長連續 1 或 0 的子串的長度。請你進行所有替換后&#xff0c;使得字符串 s 的美好值最大&#xff0c;請輸…

(二)結構型模式:1、適配器模式(Adapter Pattern)(C++實現示例)

目錄 1、適配器模式&#xff08;Adapter Pattern&#xff09;含義 2、適配器模式應用場景 3、適配器模式的UML圖學習 4、C實現適配器模式的示例 1、適配器模式&#xff08;Adapter Pattern&#xff09;含義 將一個接口轉換為客戶端所期待的接口&#xff0c;從而使兩個接口…