• 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)地址结构

    地址的数据结构

    1. 通用地址结构
    2. struct sockaddr
    3. {
    4. u_short sa_family; // 地址族, AF_xxx
    5. char sa_data[14]; // 14字节协议地址
    6. };
    7. Internet协议地址结构
    8. struct sockaddr_in
    9. {
    10. u_short sin_family; // 地址族, AF_INET,2 bytes
    11. u_short sin_port; // 端口,2 bytes
    12. struct in_addr sin_addr; // IPV4地址,4 bytes
    13. char sin_zero[8]; // 8 bytes unused,作为填充
    14. };
    15. IPv4地址结构
    16. // internet address
    17. struct in_addr
    18. {
    19. in_addr_t s_addr; // u32 network address
    20. };

    使用方法

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

    1. struct sockaddr_in myaddr;
    2. memset(&myaddr, 0, sizeof(myaddr));

    2.填充地址信息

    1. myaddr.sin_family = PF_INET;
    2. myaddr.sin_port = htons(8888);
    3. 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。例如:

    1. struct in_addr addr;
    2. 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

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

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

    头文件: #include

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

    (10)recv/recvfrom

    1. ssize_t recv(int socket, const void *buffer, size_t length, int flags);
    2. 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)套接字关闭

    1. int close(int sockfd);
    2. 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任务

    1. #include "esp_common.h"
    2. #include "freertos/FreeRTOS.h"
    3. #include "freertos/task.h"
    4. #include "lwip/sockets.h"
    5. #include "lwip/dns.h"
    6. #include "lwip/netdb.h"
    7. #include "udpclient.h"
    8. #define SERVERADDR "192.168.3.12"//注意:这是wifi分配的ip地址,会变化
    9. #define SERVERPORT 8000
    10. /******************************************************************************
    11. * FunctionName : ATaskUdpClient
    12. * Description : ATaskUdpClient 任务
    13. * Parameters : none
    14. * Returns : none
    15. *******************************************************************************/
    16. void ATaskUdpClient( void *pvParameters )
    17. {
    18. int iVariableExample = 0;
    19. int fd = -1;
    20. int NetTimeOnt = 5000;
    21. int ret;
    22. struct sockaddr_in ServerAddr;
    23. char udpmsg[48];
    24. STATION_STATUS StaStatus;
    25. do {
    26. StaStatus = wifi_station_get_connect_status();
    27. vTaskDelay(100);
    28. }while(StaStatus != STATION_GOT_IP);
    29. fd = socket(PF_INET,SOCK_DGRAM,0);
    30. if(fd == -1){
    31. printf("get socket fail!\n");
    32. vTaskDelete(NULL);
    33. }
    34. setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,&NetTimeOnt,sizeof(int));
    35. memset(&ServerAddr,0,sizeof(ServerAddr));
    36. ServerAddr.sin_family = AF_INET;
    37. ServerAddr.sin_addr.s_addr = inet_addr(SERVERADDR);
    38. ServerAddr.sin_port = htons(SERVERPORT);
    39. ServerAddr.sin_len = sizeof(ServerAddr);
    40. for(;;)
    41. {
    42. sendto(fd,"I am UdpClient!",sizeof("I am UdpClient!"),0,(struct sockaddr *)&ServerAddr,(socklen_t)ServerAddr.sin_len);
    43. do
    44. {
    45. ret = recvfrom(fd,udpmsg,48,0,(struct sockaddr *)&ServerAddr,(socklen_t*)(&ServerAddr.sin_len));
    46. if(ret > 0){
    47. printf("UdpServer:%s\n",udpmsg);
    48. }
    49. else{
    50. printf("UdpServer data is no!\n");
    51. }
    52. }while(ret == -1);
    53. }
    54. vTaskDelete( NULL );
    55. }
    56. /******************************************************************************
    57. * FunctionName : UdpClient_init
    58. * Description : UdpClient_init 初始化
    59. * Parameters : none
    60. * Returns : none
    61. *******************************************************************************/
    62. void UdpClient_init(void)
    63. {
    64. xTaskCreate(ATaskUdpClient, "UdpClient", 256, NULL, 4, NULL);
    65. }

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

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

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

    对上述代码的解释

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

    <2>创建socket

    <3>设置接收超时时间

    <4>赋值server信息

    <5>发送数据到server端

    <6>从server端接收数据

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

    1. #ifndef __UART_H__
    2. #define __UART_H__
    3. #ifdef __cplusplus
    4. extern "C" {
    5. #endif
    6. void ATaskUdpClient( void *pvParameters );
    7. void UdpClient_init(void);
    8. #ifdef __cplusplus
    9. }
    10. #endif
    11. #endif

    3.在user_main中

    UdpClient_init();

    5.运行方式

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

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

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

    运行的注意事项:连接时间比较久,稍微等一下。

            我们使用了上一节wifi入网的代码,即wifi模块加入其他网络,这里的网络必须使用4G网络,5G我的esp8266不支持。

    判断esp8266是否支持5G的方法:

            查看esp8266核心芯片的ISM为多少,2.4GHZ表示只支持4G网络,如果支持5G,器件会自己标注出来。

    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.同步文件

    3.代码实现

    1.udpserver.h

    1. #ifndef __UDPSERVER_H__
    2. #define __UDPSERVER_H__
    3. #ifdef __cplusplus
    4. extern "C" {
    5. #endif
    6. void ATaskUdpServer( void *pvParameters );
    7. void UdpServer_init(void);
    8. #ifdef __cplusplus
    9. }
    10. #endif
    11. #endif

    2.udpserver.c

    1. #include "esp_common.h"
    2. #include "freertos/FreeRTOS.h"
    3. #include "freertos/task.h"
    4. #include "lwip/sockets.h"
    5. #include "lwip/dns.h"
    6. #include "lwip/netdb.h"
    7. #include "udpserver.h"
    8. #define SERVERADDR "192.168.31.158"
    9. #define SERVERPORT 8000
    10. /******************************************************************************
    11. * FunctionName : ATaskUdpServer
    12. * Description : ATaskUdpServer 任务
    13. * Parameters : none
    14. * Returns : none
    15. *******************************************************************************/
    16. void ATaskUdpServer( void *pvParameters )
    17. {
    18. int iVariableExample = 0;
    19. int fd = -1;
    20. int NetTimeOnt = 5000;
    21. int ret;
    22. struct sockaddr_in ServerAddr;
    23. struct sockaddr from;
    24. socklen_t fromlen = sizeof(struct sockaddr);
    25. char udpmsg[48];
    26. STATION_STATUS StaStatus;
    27. do
    28. {
    29. StaStatus = wifi_station_get_connect_status();
    30. vTaskDelay(100);
    31. }while(StaStatus != STATION_GOT_IP);
    32. fd = socket(PF_INET,SOCK_DGRAM,0);
    33. if(fd == -1)
    34. {
    35. printf("get socket fail!\n");
    36. vTaskDelete(NULL);
    37. return;
    38. }
    39. setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,&NetTimeOnt,sizeof(int));
    40. memset(&ServerAddr,0,sizeof(ServerAddr));
    41. ServerAddr.sin_family = AF_INET;
    42. ServerAddr.sin_addr.s_addr = INADDR_ANY;
    43. ServerAddr.sin_port = htons(SERVERPORT);
    44. ServerAddr.sin_len = sizeof(ServerAddr);
    45. if(bind(fd,(struct sockaddr*)&ServerAddr,ServerAddr.sin_len) != 0)
    46. {
    47. printf("bind socket fail!\n");
    48. vTaskDelete(NULL);
    49. return;
    50. }
    51. for(;;){
    52. do{
    53. ret = recvfrom(fd,udpmsg,48,\
    54. 0,&from,&fromlen);
    55. if(ret > 0){
    56. printf("UdpClient:%s\n",udpmsg);
    57. }
    58. else {
    59. printf("UdpClient data is no!\n");
    60. }
    61. }while(ret == -1);
    62. sendto(fd,"I am UdpServer!",sizeof("I am UdpServer!"),\
    63. 0,&from,fromlen);
    64. }
    65. vTaskDelete( NULL );
    66. }
    67. /******************************************************************************
    68. * FunctionName : UdpServer_init
    69. * Description : UdpServer_init 初始化
    70. * Parameters : none
    71. * Returns : none
    72. *******************************************************************************/
    73. void UdpServer_init(void)
    74. {
    75. xTaskCreate(ATaskUdpServer, "UdpServer", 256, NULL, 4, NULL);
    76. }

    主函数修改

    1.加入udp服务器头文件

    2.user初始化函数中加入udp服务器初始化

    代码的详细解释

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

    2.创建socket

    3.Serveraddr 信息设置

    4.设置接收超时时间

    5.绑定socket

    6.从Client端接收数据

    7.发送数据到Client端

    运行:结果:

    1.串口调试找到wifi的IP地址(不太清楚是在哪里打印的,工程模版自带打印)

    2.使用上述wifi 的IP地址,创建一个客户端(作为模拟客户端连接)

            这里发送数据有回应(正确)

    四。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

    (1)tcpclient.h

    1. #ifndef __TCPCLIENT_H__
    2. #define __TCPCLIENT_H__
    3. #ifdef __cplusplus
    4. extern "C" {
    5. #endif
    6. void ATaskTcpClient( void *pvParameters );
    7. void TcpClient_init(void);
    8. #ifdef __cplusplus
    9. }
    10. #endif
    11. #endif

    (2)tcpclient.c

    注意:SERVERADDR为电脑的IP地址(无线网ipv4,ipconfig查找),因为电脑作为服务器,所以wifi板子需要对目标ip做出设定。

    1. #include "esp_common.h"
    2. #include "freertos/FreeRTOS.h"
    3. #include "freertos/task.h"
    4. #include "lwip/sockets.h"
    5. #include "lwip/dns.h"
    6. #include "lwip/netdb.h"
    7. #include "tcpclient.h"
    8. #define SERVERADDR "192.168.3.12"
    9. #define SERVERPORT 8000
    10. /******************************************************************************
    11. * FunctionName : ATaskTcpClient
    12. * Description : ATaskTcpClient 任务
    13. * Parameters : none
    14. * Returns : none
    15. *******************************************************************************/
    16. void ATaskTcpClient( void *pvParameters )
    17. {
    18. int iVariableExample = 0;
    19. int fd = -1;
    20. int NetTimeOnt = 5000;
    21. int ret;
    22. struct sockaddr_in ServerAddr;
    23. char Tcpmsg[48];
    24. STATION_STATUS StaStatus;
    25. do
    26. {
    27. StaStatus = wifi_station_get_connect_status();
    28. vTaskDelay(100);
    29. }while(StaStatus != STATION_GOT_IP);
    30. fd = socket(PF_INET,SOCK_STREAM,0);
    31. if(fd == -1)
    32. {
    33. printf("get socket fail!\n");
    34. vTaskDelete(NULL);
    35. }
    36. setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,&NetTimeOnt,sizeof(int));
    37. memset(&ServerAddr,0,sizeof(ServerAddr));
    38. ServerAddr.sin_family = AF_INET;
    39. ServerAddr.sin_addr.s_addr = inet_addr(SERVERADDR);
    40. ServerAddr.sin_port = htons(SERVERPORT);
    41. ServerAddr.sin_len = sizeof(ServerAddr);
    42. do
    43. {
    44. ret = connect(fd,(struct sockaddr*)&ServerAddr,ServerAddr.sin_len);
    45. if(ret != 0)
    46. {
    47. printf("connect is fail!\n");
    48. vTaskDelay(100);
    49. }
    50. }
    51. while (ret != 0);
    52. for(;;)
    53. {
    54. send(fd,"I am TcpClient!",sizeof("I am TcpClient!"),0);
    55. do
    56. {
    57. ret = recv(fd,Tcpmsg,48,0);
    58. if(ret > 0)
    59. {
    60. printf("TcpServer:%s\n",Tcpmsg);
    61. }
    62. else
    63. {
    64. printf("TcpServer data is no!\n");
    65. }
    66. }while(ret == -1);
    67. }
    68. vTaskDelete( NULL );
    69. }
    70. /******************************************************************************
    71. * FunctionName : TcpClient_init
    72. * Description : TcpClient_init 初始化
    73. * Parameters : none
    74. * Returns : none
    75. *******************************************************************************/
    76. void TcpClient_init(void)
    77. {
    78. xTaskCreate(ATaskTcpClient, "TcpClient", 256, NULL, 4, NULL);
    79. }

    user_main修改

    TcpClient_init();

    代码详细解释

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

    2.创建socket

    3.设置接收超时时间

    4.赋值server信息

    5.连接到server端

    6.发送数据到server端

    7.从server端接收数据

    4.编译:

    1.打开虚拟机,

    2.进入共享文件夹

    2.进入tcpclient工程文件

    3.编译

    (1)./gen_misc.sh 选y(回车)1(回车)2(回车)3

    出现上述表示编译成功

    5.运行。

    运行成功

    6.结果:

    电脑(服务器端发送数据有回复)

    五。实验: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)tcpserver.h

    1. #ifndef __TCPSERVER_H__
    2. #define __TCPSERVER_H__
    3. #ifdef __cplusplus
    4. extern "C" {
    5. #endif
    6. void ATaskTcpServer( void *pvParameters );
    7. void TcpServer_init(void);
    8. #ifdef __cplusplus
    9. }
    10. #endif
    11. #endif

        (2)tcpserver.c

    1. #include "esp_common.h"
    2. #include "freertos/FreeRTOS.h"
    3. #include "freertos/task.h"
    4. #include "lwip/sockets.h"
    5. #include "lwip/dns.h"
    6. #include "lwip/netdb.h"
    7. #include "tcpserver.h"
    8. #define SERVERADDR "192.168.31.158"
    9. #define SERVERPORT 8000
    10. /******************************************************************************
    11. * FunctionName : ATaskTcpServer
    12. * Description : ATaskTcpServer 任务
    13. * Parameters : none
    14. * Returns : none
    15. *******************************************************************************/
    16. void ATaskTcpServer( void *pvParameters )
    17. {
    18. int iVariableExample = 0;
    19. int fd = -1;
    20. int cfd = -1;
    21. int NetTimeOnt = 20000;
    22. int ret;
    23. struct sockaddr_in ServerAddr;
    24. struct sockaddr ClientAddr;
    25. socklen_t ClientAddrlen = sizeof(struct sockaddr);
    26. char Tcpmsg[48];
    27. STATION_STATUS StaStatus;
    28. do
    29. {
    30. StaStatus = wifi_station_get_connect_status();
    31. vTaskDelay(100);
    32. }while(StaStatus != STATION_GOT_IP);
    33. fd = socket(PF_INET,SOCK_STREAM,0);
    34. if(fd == -1)
    35. {
    36. printf("get socket fail!\n");
    37. vTaskDelete(NULL);
    38. return;
    39. }
    40. setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,&NetTimeOnt,sizeof(int));
    41. memset(&ServerAddr,0,sizeof(ServerAddr));
    42. ServerAddr.sin_family = AF_INET;
    43. ServerAddr.sin_addr.s_addr = INADDR_ANY;
    44. ServerAddr.sin_port = htons(SERVERPORT);
    45. ServerAddr.sin_len = sizeof(ServerAddr);
    46. if(bind(fd,(struct sockaddr*)&ServerAddr,ServerAddr.sin_len) != 0)
    47. {
    48. printf("bind socket fail!\n");
    49. vTaskDelete(NULL);
    50. return;
    51. }
    52. if(listen(fd,5) != 0)
    53. {
    54. printf("listen socket fail!\n");
    55. vTaskDelete(NULL);
    56. return;
    57. }
    58. for(;;)
    59. {
    60. cfd = accept(fd,&ClientAddr,&ClientAddrlen);
    61. if(cfd != -1)
    62. {
    63. ret = recv(cfd,Tcpmsg,48,0);
    64. if(ret > 0)
    65. {
    66. printf("TcpClient:%s\n",Tcpmsg);
    67. send(cfd,"I am TcpServer!",sizeof("I am TcpServer!"),0);
    68. }
    69. else
    70. {
    71. printf("TcpClient data is no!\n");
    72. }
    73. }
    74. close(cfd);
    75. }
    76. vTaskDelete( NULL );
    77. }
    78. /******************************************************************************
    79. * FunctionName : TcpServer_init
    80. * Description : TcpServer_init 初始化
    81. * Parameters : none
    82. * Returns : none
    83. *******************************************************************************/
    84. void TcpServer_init(void)
    85. {
    86. xTaskCreate(ATaskTcpServer, "TcpServer", 256, NULL, 4, NULL);
    87. }

    2.修改user_main.c

    TcpServer_init();

    代码详解

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

    2.创建socket

    3.设置接收超时时间

    4.赋值server信息

    5.绑定socket

    6.监听socket

    7.处理Client 连接

    8.接收Client 数据

    9.发送数据到Server

    10.关闭socket

    结果:

    目标地址为wifi 的打印地址(这里只能出现一次相应的原因是:每次相应客户端时候,会连接中断,看这个客户端已经显示未连接)

  • 相关阅读:
    《MATLAB科研绘图与学术图表绘制从入门到精通》示例:绘制婴儿性别比例饼图
    3.3 Tessellation Shader (TESS) & Geometry Shader(GS)
    Java面试题及答案整理(2022年140道)持续更新
    YOLO开发教程:从零开始构建自己的目标检测系统
    Promise的使用
    多商户商城系统功能拆解17讲-平台端订单列表
    慢慢欣赏linux 进程unattended-upgr CPU占用率过高定位
    Greenplum数据库故障分析——semop(id=2000421076,num=11) failed: invalid argument
    七月集训 day01(数组)
    解析:WMS仓库管理系统是什么,可以提供什么协助
  • 原文地址:https://blog.csdn.net/m0_61659911/article/details/133160857