0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于MM32F3270以太网Server_Socket使用

jf_pJlTbmA9 来源:灵动MM32MCU 作者:灵动MM32MCU 2023-09-27 15:41 次阅读

上一节我们对TCP的报文和连接过程做了介绍,本节通过Socket的方式对整个通信过程再次进行一次整理(使用Socket方式易于加深对以太网通信过程的理解,在此讲解使用的是完整版Socket)。

pYYBAGIB2LGAeMs-AADMqC3vnlU002.png

服务器端初始化

1)调用socket,向内核申请一个套接字sock

2)调用bind将sock与服务器端的IP与PORT绑定

3)调用listen将套接字设为监听模式,准备接收客户端连接请求

4)调用accept等待并接收客户端的连接请求,建立好TCP连接后,该函数会返回一个新的已连接套接字connected

创建连接

1)客户端调用socket创建套接字

2)调用connect,向服务器发送连接请求

3)connect会发送一个请求SYN段并阻塞等待服务器应答(第一次握手)

4)服务器收到SYN,会给客户端发送一个确认应答ACK,同时发送一个请求(SYN)建立连接(第二次握手)

5)客户端收到服务器发的SYN+ACK段,表明客户端连接已建立成功,进入已连接状态。客户端再向服务器发送一个ACK段,服务器收到后则服务器连接成功

数据传输

1)服务器端使用accept连接建立成功后(通信双方可同时写数据,支持全双工),调用read开始读数据,若没有数据则阻塞等待

2)客户端调用write向服务器发送数据请求,客户端收到之后调用read处理请求,此过程服务器调用read阻塞等待

3)服务器调用write将处理好的请求发送给客户端,再次调用read等待下一个请求

4)服务器收到SYN,会给客户端发送一个确认应答ACK,同时发送一个请求(SYN)建立连接(第二次握手)

4)客户端收到后从read返回,发送下一条请求,如此循环下去

断开连接

1)没有数据,则客户端调用close关闭连接,给服务器发送一个断开连接请求FIN段(第一次握手)

2)服务器收到客户端的FIN段,给客户端发送一个确认应答ACK段,表明同意断开连接。客户端收到ACK段并调用read返回0,表明客户端连接已经断开(第二次握手)

3)read返回0后,服务器知道客户端已经断开连接,它也调用close关闭连接,给客户端发送一个断开连接请求FIN段(第三次握手)

4)客户端收到服务器发送的FIN段,就给服务器一个确认应答ACK段,表明同意断开连接。客户端进入TIME_WAIT状态,服务器收到客户端的ACK段后也断开连接

poYBAGIB2LOAM497AAPsrNcBvq0265.png

实验使用MB-039开发板,在应用工程中使用LwIP+FreeRTOS,实验展示如何制作一个TCP Server_socket,并收发数据,实验使用到的硬件如下:

poYBAGIB1SyAHYynAAG39uXw7q0489.png

如图是MB-039(完整原理图可以通过MM32官网下载)的Ethermac部分。

各个信号引脚对应如下:

pYYBAGIB2LaAK68tAAAOS9P2fmc664.png
poYBAGIB1TGAFwREAAi12qR49zc411.png

Server_socket实验用到的API大部分在前面已经进行讲解(只是对NETCONN接口编辑方式进行二次封装),本节只介绍一个比较关键的API:setsockopt(s,level,optname,opval,optlen)。

从名称中就可以看出函数功能用于设置套接字的一些选项,我们关注一下参数

(1)level有多个常用的选项

SOL_SOCKET:表示在Socket层
IPPROTO_TCP:表示在TCP层
IPPROTO_IP:表示在IP层

(2)optname 表示该层的具体选项名称

level为SOL_SOCKET时,有以下选项:SO_REUSEADDR(允许重用本地地址和端口)、

SO_SNDTIMEO(设置发送数据超时时间)、SO_SNDTIMEO(设置接收数据超时时间)、SO_RCVBUF(设置发送数据缓冲区大小)等。

level为IPPROTO_TCP时,有以下选项:TCP_NODELAY(不使用Nagle算法)、TCP_KEEPALIVE(设置TCP保活时间)等。

level为IPPROTO_IP选项,有以下选项:IP_TTL(设置生存时间)、IP_TOS(设置服务类型)等。

实现Server_socket函数:

static void server_socket(void* thread_param)
{ 
    int sock = -1, connected;
    char* recv_data;
    struct sockaddr_in server_addr, client_addr;
    socklen_t sin_size;
    int recv_data_len;

    printf("The local port number is%dnn", LOCAL_PORT);
    recv_data = (char*)pvPortMalloc(RECV_DATA);
    if (recv_data == NULL) {
        printf("No memoryn");
        goto __exit;
    }
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        printf("Socket errorn");
        goto __exit;
    }
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(LOCAL_PORT);
    memset( (server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
    if (bind(sock, (struct sockaddr*) server_addr, sizeof(struct sockaddr)) == -1) {
        printf("Unable to bindn");
        goto __exit;
    }
    if (listen(sock, 5) == -1) {                         // (1)
        printf("Listen errorn");
        goto __exit;
    }
    while(1) {
        sin_size = sizeof(struct sockaddr_in);
        connected = accept(sock, (struct sockaddr*) client_addr,  sin_size);  // (2)
        printf("new client connected from (%s, %d)n",
               inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
        {
            int flag = 1;
            setsockopt(connected,
                       IPPROTO_TCP,     /* set option at TCP level */
                       TCP_NODELAY,     /* name of option */
                       (void*)  flag,   /* the cast is historical cruft */
                       sizeof(int));    /* length of option value */      // (3)
        }
        while(1) {
            recv_data_len = recv(connected, recv_data, RECV_DATA, 0);    // (4)
            if (recv_data_len <= 0)
                break;
            printf("recv %d len datan", recv_data_len);
            write(connected, recv_data, recv_data_len);   // (5)
        }
        if (connected >= 0)
            closesocket(connected);                  //  (6)
        connected = -1;
    }
__exit:
    if (sock >= 0) closesocket(sock);
    if (recv_data) free(recv_data);
}

1)进入监听状态

2)阻塞应用线程直至与远端主机建立TCP连接,建立成功后远程主机的信息将保持在连接句柄中(connected)

3)对套接字connected进行设置:在TCP层,不使用Nagle算法

4)处理客户端的连接请求,接收远程主机信息

5)将接收的数据进行转发

6)主动关闭客户端的连接

到这里已经完成了Server_socket函数的创建,看一下PC的IP地址,设备需要处于同一网段方便测试。打开命令行窗口输入:ipconfig

pYYBAGIB1TOARaWcAAEnlBhO5H8936.png

PC的地址为:192.168.105.34,在sys_arch.h文件中对DEST_IP_ADDR0 、DEST_IP_ADDR1、DEST_IP_ADDR2、DEST_IP_ADDR3进行修改,DEST_PORT 随意修改。

#define LOCAL_PORT                 2021

#define IP_ADDR0                    192
#define IP_ADDR1                    168
#define IP_ADDR2                    105
#define IP_ADDR3                    26

将程序下载入开发板中,使用NetAssist进行如下设置:

1)协议设置,此时设备为Server,则PC为Client

2)设置远程主机地址(即设备地址)

3)端口号

poYBAGIB2LqAdSiQAAFh-INvmSs790.png

点击连接,若提示连接失败,则Ping一下开发板地址,可以正常Ping通则检查端口号;如果无法Ping通则需要对工程进行检查。

pYYBAGIB2L2ABDnEAAFu311zkS8170.png

任意输入字符进行发送。

pYYBAGIB2L-ABHo3AAItUIKKqj8606.png

通过上图可以观察到发送成功,并且设备返回数据与发送数据一致,表明实验成功。

实验程序请登录我们的官网下载MM32F3270 SDK,工程路径如下:

~MM32F3270_Lib_Samples_V0.90Demo_appEthernet_DemoETH_RTOSFreertos_Server_socket

来源:灵动MM32MCU

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 以太网
    +关注

    关注

    40

    文章

    5425

    浏览量

    171725
  • 通信
    +关注

    关注

    18

    文章

    6032

    浏览量

    135995
  • Server
    +关注

    关注

    0

    文章

    90

    浏览量

    24037
  • TCP
    TCP
    +关注

    关注

    8

    文章

    1353

    浏览量

    79074
收藏 人收藏

    评论

    相关推荐

    灵动微课堂 (第182讲) | 基于MM32F3270 以太网 Client_Socket使用

    :~\MM32F3270_Lib_Samples_V0.90\Demo_app\Ethernet_Demo\ETH_RTOS\Freertos_Client_socket下章的题目为《基于MM32F3270
    发表于 10-18 11:02

    灵动微课堂 (第183讲) | 基于MM32F3270 以太网 Server_Socket使用

    :~\MM32F3270_Lib_Samples_V0.90\Demo_app\Ethernet_Demo\ETH_RTOS\Freertos_Server_socket我们下节的题目为《基于MM32F3270
    发表于 10-18 11:08

    MM32F3270系列32位MCU的特点有哪些

    上海灵动微电子推出全新主流型MM32F3270系列32位MCU,此款MM32F3270系列是基于M3内核的32位微控制器,MM32F3270适用于要求高集成度的高性能控制领域,如:工业控制、消防监控
    发表于 11-03 07:20

    灵动微电子MM32F3270系列MCU的特点介绍

    上海灵动微电子推出全新主流型MM32F3270系列32位MCU,此款MM32F3270系列是基于M3内核的32位微控制器,MM32F3270适用于要求高集成度的高性能控制领域,如:工业控制、消防监控
    发表于 03-22 16:57 2163次阅读

    【国产MCU移植】MM32F3270 EVBoard

    【国产MCU移植】MM32F3270 EVBoard
    发表于 12-03 17:21 5次下载
    【国产MCU移植】<b class='flag-5'>MM32F3270</b> EVBoard

    基于MM32F3270 以太网 Client使用

    接下来给大家介绍基于TCP包的通讯。内容分为基于MM32F3270以太网Client的使用与基于MM32F3270以太网Server的使用。
    发表于 02-08 15:10 0次下载
    基于<b class='flag-5'>MM32F3270</b> <b class='flag-5'>以太网</b> Client使用

    基于MM32F3270 以太网 Server_Socket使用

    本节通过Socket的方式对整个通信过程再次进行一次整理(使用Socket方式易于加深对以太网通信过程的理解,在此讲解使用的是完整版Socket)。
    发表于 02-08 15:17 0次下载
    基于<b class='flag-5'>MM32F3270</b> <b class='flag-5'>以太网</b> <b class='flag-5'>Server_Socket</b>使用

    MM32F3270 ADC注入通道

    MM32F3270 ADC注入通道
    的头像 发表于 09-27 15:59 1000次阅读
    <b class='flag-5'>MM32F3270</b> ADC注入通道

    使用MM32F3270 FSMC驱动OLED

    使用MM32F3270 FSMC驱动OLED
    的头像 发表于 09-27 15:30 954次阅读
    使用<b class='flag-5'>MM32F3270</b> FSMC驱动OLED

    使用MM32F3270 FSMC驱动TFT-LCD

    使用MM32F3270 FSMC驱动TFT-LCD
    的头像 发表于 09-27 15:34 1042次阅读
    使用<b class='flag-5'>MM32F3270</b> FSMC驱动TFT-LCD

    基于MM32F3270以太网HTTP使用

    基于MM32F3270以太网HTTP使用
    的头像 发表于 09-27 15:48 574次阅读
    基于<b class='flag-5'>MM32F3270</b><b class='flag-5'>以太网</b>HTTP使用

    基于MM32F3270以太网Server使用

    基于MM32F3270以太网Server使用
    的头像 发表于 09-27 15:46 502次阅读
    基于<b class='flag-5'>MM32F3270</b><b class='flag-5'>以太网</b><b class='flag-5'>Server</b>使用

    基于MM32F3270以太网Client使用

    基于MM32F3270以太网Client使用
    的头像 发表于 09-27 15:44 708次阅读
    基于<b class='flag-5'>MM32F3270</b><b class='flag-5'>以太网</b>Client使用

    基于MM32F3270以太网UDP使用

    基于MM32F3270以太网 UDP使用
    的头像 发表于 09-27 15:42 501次阅读
    基于<b class='flag-5'>MM32F3270</b><b class='flag-5'>以太网</b>UDP使用

    基于MM32F3270以太网Client_Socket使用

    基于MM32F3270以太网Client_Socket使用
    的头像 发表于 09-27 15:37 543次阅读
    基于<b class='flag-5'>MM32F3270</b><b class='flag-5'>以太网</b>Client_<b class='flag-5'>Socket</b>使用