3.wifi开发,网络编程

网络协议栈LwIP

WiFi UDP Clinet编程

WiFi UDP Server编程

WiFi TCP Client编程

WiFi TCP Server编程

一。LWIP原理介绍,API介绍,文件结构

1.Lwip支持的协议

2.API

3.文件结构

1.api目录:应用程序接口文件。

2.arch目录:与硬件和OS有关的文件,包括网络驱动、移植需要修改的文件。

3.core目录:LwIP的核心代码,包括ICMP、IP、UDP、TCP等协议的实现等。

4.include目录:LwIP的包含文件。

5.netif目录:PPP协议和LwIP网络设备驱动程序的模板,提供了网络接口驱动程序的基本框架。

4.Socket 通信模型

Socket是一个网络编程接口

Socket类型:

(1)流式套接字(SOCK_STREAM)

(2)数据报套接字(SOCK_DGRAM)

(3)原始套接字(SOCK_RAW)

5.Socket API

socket:创建一个套接字

bind:将本地端口号和IP地址绑定到套接字上

listen:TCP监听

accept:TCP监听接受处理

connect:TCP客户端连接

select:特殊套接字设置

send/sendto:发送数据包到已连接/未连接套接字上

recv/recvfrom:接收数据包从已连接/未连接套接字上

getsockopt/setsockopt:获取/改变套接字选项

getpeername/getsockname:获取远端/本地地址信息

close:关闭套接字

shutdown:按设置关闭套接字

gethostbyname/gethostbyaddr:地址域名映射

read:从套接字缓存读数据

write:向套接字缓存写数据

目的:

Lwip协议栈的实现目的,无非是要上层用来实现app的socket编程。 为了兼容性,lwip的socket通过宏定义提供标准的socket接口函数

5.介绍常用的API

(1)int socket (int domain, int type, int protocol);

        1.domain 是地址族

PF_INET  // internet IPv4协议

PF_INET6 // internet IPv6协议

PF_UNSPEC      // 用户协议

        2.type  // 套接字类型

SOCK_STREAM   // 流式套接字

SOCK_DGRAM    // 数据报套接字 S

OCK_RAW         //  原始套接字

        3.protocol //参数通常置为0     

IPPROTO_IP      0     

IPPROTO_TCP     6     

IPPROTO_UDP     17

(2)int bind (int sockfd, struct sockaddr* addr, int addrLen);

        1.sockfd 由socket() 调用返回

        2.addr 是指向 sockaddr_in 结构的指针,包含本机IP 地址和端口号

struct sockaddr_in{

        u_short sin_family // protocol family

        u_short sin_port     // port number

}

struct in_addr  sin_addr  //IP address (32-bits)
        3.addrLen : sizeof (struct sockaddr_in)

(3)地址结构

地址的数据结构

通用地址结构struct sockaddr{    u_short  sa_family;    // 地址族, AF_xxxchar  sa_data[14];     // 14字节协议地址};Internet协议地址结构struct sockaddr_in{           u_short sin_family;      // 地址族, AF_INET,2 bytesu_short sin_port;      // 端口,2 bytesstruct in_addr sin_addr;  // IPV4地址,4 bytes 	char sin_zero[8];        // 8 bytes unused,作为填充}; 
IPv4地址结构
// internet address  
struct in_addr
{in_addr_t  s_addr;            // u32 network address 
};

使用方法

1.定义一个struct sockaddr_in类型的变量并清空

struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));

2.填充地址信息

myaddr.sin_family = PF_INET;
myaddr.sin_port = htons(8888); 
myaddr.sin_addr.s_addr = inet_addr(“192.168.1.100”);

3.将该变量强制转换为struct sockaddr类型在函数中使用

bind(listenfd, (struct sockaddr*)(&myaddr), sizeof(myaddr));

(4)地址转换函数

1.unsigned long inet_addr(char *address);

        address是以’\0’结尾的点分IPv4字符串。该函数返回32位的地址。如果字符串包含的不是合法的IP地址,则函数返回-1。例如:

struct in_addr addr;
addr.s_addr = inet_addr(" 192.168.1.100 ");

2.char* inet_ntoa(struct in_addr address);

        address是IPv4地址结构,函数返回一指向包含点分IP地址的静态存储区字符指针。如果错误则函数返回NULL。

(5)获取/发送套接字

获取套接字

int getsockopt(int sock, int level,int optname, void *optval, socklen_t *optlen);

发送套接字

int setsockopt(int sock, int level,int optname, const void *optval, socklen_t optlen);

参数:

sock:将要被设置或者获取选项的套接字。

level:选项所在的协议层。

optname:需要访问的选项名。

optval:对于getsockopt(),指向返回选项值的缓冲。对于setsockopt(),指向包含新选项值的缓冲。

optlen:对于getsockopt(),作为入口参数时,选项值的最大长度。作为出口参数时,选项值的实际长度。对于setsockopt(),现选项的长度。

返回说明: 成功执行时,返回0。

失败返回-1,errno被设为以下的某个值

EBADF:sock不是有效的文件描述词

EFAULT:optval指向的内存并非有效的进程空间

EINVAL:在调用setsockopt()时,optlen无效

ENOPROTOOPT:指定的协议层不能识别选项

ENOTSOCK:sock描述的不是套接字

(6)listen监听

int listen (int sockfd, int backlog);

sockfd:监听连接的套接字。

backlog 指定了正在等待连接的最大队列长度,它的作用在于处理可能同时出现的几个连接请求。 DoS(拒绝服务)攻击即利用了这个原理,非法的连接占用了全部的连接数,造成正常的连接请求被拒绝。 返回值: 0 或 -1。

完成listen()调用后,socket变成了监听socket(listening socket).

(7)accept

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) ;

返回值:已建立好连接的套接字或-1
sockfd : 监听套接字 
addr : 对方地址
addrlen:地址长度

(8)connect

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

返回值:0 或 -1

sockfd : socket返回的文件描述符

serv_addr : 服务器端的地址信息  

addrlen : serv_addr的长度

(9)send/sendto

ssize_t  send(int  socket,  const  void  *buffer,  size_t  length, int flags);
ssize_t  sendto(int s, const void *data, size_t size, int flags,const struct sockaddr *to, socklen_t tolen);

返回值: 成功:实际发送的字节数 失败:-1, 并设置errno

头文件: #include <sys/socket.h>

buffer : 发送缓冲区首地址 length : 发送的字节数 flags : 发送方式(通常为0)

(10)recv/recvfrom

ssize_t  recv(int  socket,  const  void  *buffer,  size_t  length, int flags);
ssize_t  recvfrom(int s, void *mem, size_t len, int flags,struct sockaddr *from, socklen_t *fromlen);

返回值: 成功:实际接收的字节数 失败:-1,并设置errno

buffer : 发送缓冲区首地址

length : 发送的字节数

flags : 接收方式(通常为0)

(11)套接字关闭

int close(int sockfd);
int shutdown(int sockfd, int howto);

close是双向通信的关闭

TCP连接是双向的(是可读写的),当我们使用close时,会把读写通道都关闭,有时侯我们希望只关闭一个方向,这个时候我们可以使用shutdown。针对不同的howto,系统回采取不同的关闭方式。 howto = 0 关闭读通道,但是可以继续往套接字写数据。 howto = 1 和上面相反,关闭写通道。只能从套接字读取数据。 howto = 2 关闭读写通道,和close()一样

二。实验:WiFi UDP Clinet编程

1.功能分析

完成UDP Client功能开发

(1)PC模拟UDP Server,指定(IP,PORT),等待Client数据

(2)UDP Client向Sever发送“I am Client!”

(3)Sever收到数据后,向Client发送“I am Server!”

2.功能实现

(1)在SDK目录下新建udpclient目录

(2)拷贝Station目录下所有文件到udpclient目录下

(3)在user目录下新建udpclient.c

(4)在include目录下新建udpclient.h

(1)Sourceinsight配置

在之前的工程中,移除AP文件夹 添加udpclient文件夹

添加lwip文件夹

同步:

发现的问题:

QQ的截屏比SourceInsight复制优先级低,即先复制代码,在截屏之后粘贴还是复制的代码

3.代码实现

1.在udpclient.c下,添加《整体复制粘贴

(1)udpclient初始化

(2)udpclient任务

#include "esp_common.h"#include "freertos/FreeRTOS.h"
#include "freertos/task.h"#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"
#include "udpclient.h"#define SERVERADDR "192.168.3.12"//注意:这是wifi分配的ip地址,会变化
#define SERVERPORT 8000
/******************************************************************************* FunctionName : ATaskUdpClient* Description  : ATaskUdpClient 任务* Parameters   : none* Returns      : none
*******************************************************************************/
void ATaskUdpClient( void *pvParameters )
{int iVariableExample = 0;int fd = -1;int NetTimeOnt = 5000;int ret;struct sockaddr_in ServerAddr;char udpmsg[48];STATION_STATUS StaStatus;do {StaStatus = wifi_station_get_connect_status();vTaskDelay(100);}while(StaStatus != STATION_GOT_IP);fd = socket(PF_INET,SOCK_DGRAM,0);if(fd == -1){printf("get socket fail!\n");vTaskDelete(NULL);}setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,&NetTimeOnt,sizeof(int));memset(&ServerAddr,0,sizeof(ServerAddr));ServerAddr.sin_family = AF_INET;ServerAddr.sin_addr.s_addr = inet_addr(SERVERADDR);ServerAddr.sin_port = htons(SERVERPORT);ServerAddr.sin_len = sizeof(ServerAddr);for(;;){sendto(fd,"I am UdpClient!",sizeof("I am UdpClient!"),0,(struct sockaddr *)&ServerAddr,(socklen_t)ServerAddr.sin_len);do{ret = recvfrom(fd,udpmsg,48,0,(struct sockaddr *)&ServerAddr,(socklen_t*)(&ServerAddr.sin_len));if(ret > 0){printf("UdpServer:%s\n",udpmsg);}else{printf("UdpServer data is no!\n");}}while(ret == -1);}vTaskDelete( NULL );
}
/******************************************************************************* FunctionName : UdpClient_init* Description  : UdpClient_init 初始化* Parameters   : none* Returns      : none
*******************************************************************************/
void UdpClient_init(void)
{xTaskCreate(ATaskUdpClient, "UdpClient", 256, NULL, 4, NULL);
}

 注意:上述的IPv设置的是本机的IP地址

Win+R---》cmd进入命令行

输入ipconfig查询无线网络ipv4地址

对上述代码的解释

<1>判断是否获取到IP地址

<2>创建socket

<3>设置接收超时时间

<4>赋值server信息

<5>发送数据到server端

<6>从server端接收数据

2.在udpclient.h下声明《整体复制》

#ifndef __UART_H__
#define __UART_H__#ifdef __cplusplus
extern "C" {
#endifvoid ATaskUdpClient( void *pvParameters );
void UdpClient_init(void);#ifdef __cplusplus
}
#endif#endif

3.在user_main中

UdpClient_init();

5.运行方式

(1)创建一个UDP,ip为本机被分配的无线ipv4地址,端口为程序代码设置的端口

查询IP地址(通过ipconfig命令获取本机ip地址

(2)建立串口通讯,波特率为74880,关闭RTS,使用终端模式

4.结果

(1)串口中打印从UDP服务器传输过来的数据(123)

三。实验:WiFi UDP Server编程

1.功能分析

实验要求:
完成UDP Server功能开发

1.PC模拟UDP Client,指定UDP Server (IP,PORT),发送“I am Client!”

2.Sever收到数据后,向Client发送“I am Server!”

2.功能实现

新建udpserver工程目录

1.在SDK目录下新建udpserver目录

2.拷贝udpclient目录下所有文件到udpserver目录下

新建udpserver源码文件

1.在user目录下新建udpserver.c

2.在include目录下新建udpserver.h

Sourceinsight配置

1.在之前的工程中,移除udpclient文件夹

2.添加udpserver文件夹

3.代码实现

1.复制之前udpclient代码到udpserver上,进行修改

    (1)重命名UdpClient_init为UdpServer_init

    (2)重命名ATaskUdpClient为ATaskUdpServer

2.修改user_main.c

    (1)包涵udpserver.h

    (2)在user_init里修改为UdpServer_init

代码的详细解释

1.判断是否获取到IP地址

2.创建socket

3.Serveraddr 信息设置

4.设置接收超时时间

5.绑定socket

6.从Client端接收数据

7.发送数据到Client端

结果:

四。WiFi TCP Client编程

1.功能分析

实验要求:

完成TCP Client功能开发

1.PC模拟TCP Server,指定(IP,PORT),等待Client数据

2.TCP Client向Sever发送“I am Client!”

3.Sever收到数据后,向Client发送“I am Server!”

2.功能实现

新建tcpclient工程目录

1.在SDK目录下新建tcpclient目录

2.拷贝udpclient目录下所有文件到tcpclient目录下

新建tcpclient源码文件

1.在user目录下新建tcpclient.c

2.在include目录下新建tcpclient.h

Sourceinsight配置

1.在之前的工程中,移除udpserver文件夹

2.添加tcpclient文件夹

3.代码实现

1.复制之前udpclient代码到tcpclient上,进行修改

    (1)重命名UdpClient_init为TcpClient_init

    (2)重命名ATaskUdpClient为ATaskTcpClient

2.修改user_main.c

    (1)包涵tcpclient.h

    (2)在user_init里修改为TcpClient_init

代码详细解释

1.判断是否获取到IP地址

2.创建socket

3.设置接收超时时间

4.赋值server信息

5.连接到server端

6.发送数据到server端

7.从server端接收数据

五。实验:WiFi TCP Server编程

1.功能分析

实验要求:

完成TCP Server功能开发

1.PC模拟TCP Client,指定Server(IP,PORT)

    (1)进行连接,连接成功后发生“I am Client!”

    (2)Sever收到数据后,向Client发送“I am Server!”

2.功能实现

新建tcpserver工程目录

1.在SDK目录下新建tcpserver目录

2.拷贝tcpclient目录下所有文件到tcpserver目录下

新建tcpserver源码文件

1.在user目录下新建tcpserver.c

2.在include目录下新建tcpserver.h

Sourceinsight配置

1.在之前的工程中,移除tcpclient文件夹

2.添加tcpserver文件夹

3.代码实现

1.复制之前tcpclient代码到tcpserver上,进行修改

    (1)重命名TcpClient_init为TcpServer_init

    (2)重命名ATaskTcpClient为ATaskTcpServer

2.修改user_main.c

    (1)包涵tcpserver.h

    (2)在user_init里修改为TcpServer_init

代码详解

1.判断是否获取到IP地址

2.创建socket

3.设置接收超时时间

4.赋值server信息

5.绑定socket

6.监听socket

7.处理Client 连接

8.接收Client 数据

9.发送数据到Server

10.关闭socket

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

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

相关文章

k8s master 是如何进行pod的调度的

Master 节点将 Pod 调度到指定的 Node 节点的原理 该工作由 kube-scheduler 来完成&#xff0c;整个调度过程通过执行一些列复杂的算法最终为每个 Pod 计算出一个最佳的目标 Node&#xff0c;该过程由 kube-scheduler 进程自动完成。常见的有轮询调度&#xff08;RR&#xff09…

Chrome浏览器删除网站cookies的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

[论文笔记]P-tuning v2

引言 今天带来第五篇大模型微调论文笔记P-tuning v2: Prompt Tuning Can Be Comparable to Fine-tuning Across Scales and Tasks。 作者首先指出了prompt tuning的一些不足,比如在中等规模的模型上NLU任务表现不好,还不能处理困难的序列标记任务,缺乏统一应用的能力。 然…

安卓系统--翻译手机rom语言 添加多国语言 编译apk 反编译ODEX 工具步骤解析

很多小品牌机型不具备多语言设置。国内大都是中文。要想换为其他语言除非固件支持。例如国际版固件等等。大厂基本都有中文或者英文或者其他语言配置。而小品牌机型只能通过修改rom来达到多语言调用. 工具步骤演示 今天给友友介绍一款工具&#xff0c;可以用来翻译手机rom语言…

LinkedList相较于Arravlist的特点/优化

Arravlist底层是内存空间连续的数组&#xff0c;可以根据下标进行随机访问&#xff0c;效率比较高&#xff0c;因为在根据下标访问某一个元素时&#xff0c;并不是一个一个去查&#xff0c;而是算出来这个下标的地址&#xff0c;直接根据这个地址的指向去获取的&#xff0c;因为…

Android Key/Trust Store研究+ssl证书密钥

前言&#xff1a;软件搞环境涉及到了中间件thal trustzone certificate key&#xff0c;翻译过来是thal信任区域证书密钥 &#xff0c;不明白这是什么&#xff0c;学习一下 ssl证书密钥 SSL密钥是SSL加密通信中的重要组成部分。SSL证书通过加密算法生成&#xff0c;用于保护网…

思科路由器:NAT的基础配置

一直以来&#xff0c;对于华为、H3C、锐捷交换机的命令配置&#xff0c;不断的有朋友留言&#xff0c;三家交换机的配置命令容易弄混&#xff0c;经常在实际项目配置中出错&#xff0c;因此&#xff0c;找几个基础的示例来练练。 R1配置 Router>en Router>enable Rout…

Apifox接口测试工具详细解析

最近发现一款接口测试工具--apifox&#xff0c;我我们很难将它描述为一款接口管理工具 或 接口自测试工具。 官方给了一个简单的公式&#xff0c;更能说明apifox可以做什么。 Apifox Postman Swagger Mock JMeter Apifox的特点&#xff1a; 接口文档定义&#xff1a; Api…

2023华为杯D题——基于Kaya模型的碳排放达峰实证研究

一、前言 化石能源是推动现代经济增长的重要生产要素&#xff0c;经济生产活动与碳排放活动密切相关。充分认识经济增长与碳排放之间的关系对转变生产方式&#xff0c;确定碳达峰、碳中和路径极为必要。本研究在对经济增长与碳排放关系现有研究梳理的基础上&#xff0c;系统地分…

【2023年中国研究生数学建模竞赛华为杯】E题 出血性脑卒中临床智能诊疗建模 问题分析、数学模型及代码实现

【2023年中国研究生数学建模竞赛华为杯】E题 出血性脑卒中临床智能诊疗建模 1 题目 1.1 背景介绍 出血性脑卒中指非外伤性脑实质内血管破裂引起的脑出血&#xff0c;占全部脑卒中发病率的10-15%。其病因复杂&#xff0c;通常因脑动脉瘤破裂、脑动脉异常等因素&#xff0c;导致…

iOS17.0.2更新修复iPhone 15系列机型数据迁移问题,附新机快速数据迁移办法!

iPhone 15 系列机型已于今日正式发售&#xff0c;为解决iPhone15这些机型出现的数据迁移问题&#xff0c;苹果紧急发布了 iOS 17.0.2 更新&#xff0c;内部版本号为 21A350。 需要注意的是&#xff0c; iOS 17.0.2 更新仅适用于 iPhone 15、iPhone 15 Plus、iPhone 15 Pro 和 …

中兴R5300 G4服务器iSAC管理员zteroot密码遗失的重置方法及IPV6地址启用设置

本文讲解中兴R5300 G4服务器BMC带外iSAC管理员zteroot密码遗失&#xff0c;无法登录时如何对其进行密码重置&#xff0c;以及iSAC启用IPV6地址的方法。 一、重置中兴R5300 G4服务器iSAC管理员zteroot密码 1、通过SSH登录到iSAC&#xff0c;默认用户名&#xff1a;sysadmin&am…

科普之加密、签名和SSL握手

一 背景知识 感悟&#xff1a; 不能高不成低不就备注&#xff1a; 以下内容没有逻辑排版,仅做记录 ① 加密方式 说明&#xff1a; 单向和双向认证遗留&#xff1a; 如何用openssl从私钥中提取公钥? ② 互联网数据安全可靠条件 说明&#xff1a; 二者相互印证 二 互联…

Windows专业版的Docker下载、安装与启用Kubenetes、访问Kubernetes Dashboard

到Docker 官网https://www.docker.com/ 下载windows操作系统对应的docker软件安装 Docker Desktop Installer-Win.exe 2023-09版本是4.23 下载后双击安装 重启windows后&#xff0c;继续安装 接受服务继续安装 解决碰到的Docker Engine stopped 打开 控制面板》程序》启用或关…

成为威胁:网络安全中的动手威胁模拟案例

不断变化的网络威胁形势要求组织为其网络安全团队配备必要的技能来检测、响应和防御恶意攻击。然而&#xff0c;在研究中发现并继续探索的最令人惊讶的事情是&#xff0c;欺骗当前的网络安全防御是多么容易。 防病毒程序建立在庞大的签名数据库之上&#xff0c;只需更改程序内…

jupyterlab开发环境最佳构建方式

文章目录 背景jupyterlab环境构建运行虚拟环境构建以及kernel映射验证总结 背景 从jupyter notebook切换到了jupyter lab. 这里记录一下本地环境的最佳构建方式. jupyter lab 安装在jupyterlab-local的anaconda 虚拟环境中.建立多个其他虚拟环境安装各种python包实现环境隔离,…

Untiy UDP局域网 异步发送图片

同步画面有问题&#xff0c;传图片吧 using System.Text; using System.Net.Sockets; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using System.Net; using System; using System.Threading.Tasks; using Sy…

Android studio中如何下载sdk

打开 file -> settings 这个页面, 在要下载的 SDK 前面勾上, 然后点 apply 在 platforms 中就可以看到下载好的 SDK: Android SDK目录结构详细介绍可以参考这篇文章: 51CTO博客- Android SDK目录结构

一招解除csdn复制限制

先看这个代码 python读取英文pdf翻译成中文pdf文件导出代码 想要复制代码&#xff0c;csdn有限制怎么办&#xff08;csdn流氓&#xff0c;无耻&#xff09; 解除方法 ctrlu 看效果

什么是分布式锁?他解决了什么样的问题?

相信对于朋友们来说&#xff0c;锁这个东西已经非常熟悉了&#xff0c;在说分布式锁之前&#xff0c;我们来聊聊单体应用时候的本地锁&#xff0c;这个锁很多小伙伴都会用 ✔本地锁 我们在开发单体应用的时候&#xff0c;为了保证多个线程并发访问公共资源的时候&#xff0c;…