完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
前面重点对Client的创建方式及使用方式进行了介绍,本节通过Server实验对TCP通信过程进行一次介绍。 在TCP/IP协议中,传输层及以下层的机制是由内核提供的。应用层由用户提供,应用层程序对通信数据进行解析处理,传输层及以下层处理通信的细节(将数据从一端传入另外一端)。应用层数据通过协议栈发送到网络上时,每层协议都要增加一个数据部首(header),进行一次封装。其中不同的协议层对数据包有不同的称谓,在传输层叫段(segment),在网络层叫做数据报(datagram),在链路层称为帧(frame)。
在通信过程中,发送端执行以下动作:首先程序进行编码,确定通信的建立连接、发送数据的时间。接着建立TCP连接,TCP根据应用指示负责建立连接、发送数据及断开连接。TCP首部包括源端口号和目标端口号、序号和校验和,加完首部后数据包继续往下传递到IP层,IP层加上IP首部包括地址等信息用于寻址操作,之后将数据继续往下传递附加数据链路层首部。最后发送时的分组数据包会加上以太网包尾(用于循环冗余校验)。 主机端:收到数据包后会在以太网数据包中找到MAC地址,判断是否为自己的数据包,如果不是则丢弃。如果是传递给IP层处理,以此类推,不断往上传递到TCP层。在TCP层通过校验和判断数据是否损坏,然后检查是否按序号接收数据,最后检查端口号。处理完成这一切后数据包继续往上层发送,即应用层。如果出现主机空间已满等情况,主机则会发送“处理异常”通知发送端。 各个信号引脚对应如下: 1)netconn_bind () 2)netconn_listen () 3)netconn_accept () 以下分API展开介绍: 01 netconn_bind () 从源码中可以看出其主要功能:为conn(服务器端)绑定地址与端口号。 err_t netconn_bind(struct netconn* conn, const ip_addr_t* addr, u16_t port) { API_MSG_VAR_DECLARE(msg); err_t err; LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); #if LWIP_IPV4 /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ if (addr == NULL) { addr = IP4_ADDR_ANY; } #endif /* LWIP_IPV4 */ #if LWIP_IPV4 && LWIP_IPV6 if ((netconn_get_ipv6only(conn) == 0) && ip_addr_cmp(addr, IP6_ADDR_ANY)) { addr = IP_ANY_TYPE; } #endif /* LWIP_IPV4 && LWIP_IPV6 */ API_MSG_VAR_ALLOC(msg); API_MSG_VAR_REF(msg).conn = conn; API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); API_MSG_VAR_REF(msg).msg.bc.port = port; err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); API_MSG_VAR_FREE(msg); return err; } 02 netconn_listen () netconn_listen指向的函数是:netconn_listen_with_backlog,作用:使服务器进入监听状态,等待远端的连接请求。 err_t netconn_listen_with_backlog(struct netconn* conn, u8_t backlog) { #if LWIP_TCP API_MSG_VAR_DECLARE(msg); err_t err; /* This does no hARM. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ LWIP_UNUSED_ARG(backlog); LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); API_MSG_VAR_ALLOC(msg); API_MSG_VAR_REF(msg).conn = conn; #if TCP_LISTEN_BACKLOG API_MSG_VAR_REF(msg).msg.lb.backlog = backlog; #endif /* TCP_LISTEN_BACKLOG */ err = netconn_apimsg(lwip_netconn_do_listen, &API_MSG_VAR_REF(msg)); API_MSG_VAR_FREE(msg); return err; #else /* LWIP_TCP */ LWIP_UNUSED_ARG(conn); LWIP_UNUSED_ARG(backlog); return ERR_ARG; #endif /* LWIP_TCP */ } 03 netconn_accept () netconn_accept(代码较长,这里不进行粘贴)用于TCP服务器中,等待着远端主机的连接请求,并且建立一个新的TCP连接,在调用这个函数之前需要通过调用 listen()函数让服务器进入监听状态。accept()函数的调用会阻塞应用线程直至与远程主机建立TCP连接。参数addr是一个返回结果参数,它的值由accept()函数设置,其实就是远程主机的地址与端口号等信息,当新的连接已经建立后,远端主机的信息将保存在连接句柄中,能够标识连接对象。 了解了以上3个API,我们开始创建Server工程: static void server(void* thread_param) { struct netconn* conn, *newconn; err_t err; LWIP_UNUSED_ARG(arg); #if LWIP_IPV6 conn = netconn_new(NETCONN_TCP_IPV6); netconn_bind(conn, IP6_ADDR_ANY, LOCAL_PORT); #else /* LWIP_IPV6 */ conn = netconn_new(NETCONN_TCP); //① netconn_bind(conn, IP_ADDR_ANY, LOCAL_PORT); //② #endif /* LWIP_IPV6 */ LWIP_ERROR("tcpecho: invalid conn", (conn != NULL), return;); printf("The local port number is%dnn", LOCAL_PORT); netconn_listen(conn); //③ while (1) { err = netconn_accept(conn, &newconn); //④ if (err == ERR_OK) { struct netbuf* buf; void* data; u16_t len; while ((err = netconn_recv(newconn, &buf)) == ERR_OK) { //⑤ do { netbuf_data(buf, &data, &len); err = netconn_write(newconn, data, len, NETCONN_COPY); //⑥ } while (netbuf_next(buf) >= 0); netbuf_delete(buf); //⑦ } netconn_close(newconn); //⑧ netconn_delete(newconn); //⑨ } } }1 申请一个连接结构,指定参数是NETCONN_TCP,即TCP连接 2 绑定本地的IP地址与端口号 3 使TCP服务器进入监听状态 4 处理客户端的连接请求,当只有当有客户端发送连接请求的时候才会处理,否则将进入阻塞态,而客户端的信息保存在newconn连接结构中 5 接收数据,并装填进buf 6 对接收的数据进行转发(指定为不拷贝方式NETCONN_COPY) 7 释放数据空间 8 主动关闭客户端的连接 9 释放newconn空间 到这里已经完成了工程的创建,看一下PC的IP地址,设备需要处于同一网段,以方便测试。 打开命令行窗口输入:ipconfig #define IP_ADDR0 192 #define IP_ADDR1 168 #define IP_ADDR2 105 #define IP_ADDR3 21 将程序下载入开发板中,使用NetAssist进行如下设置: 1)协议设置,此时设备为Server,则PC为Client 2)设置远程主机地址(即设备地址) 3)端口号 我们下章的题目为《基于MM32F3270 以太网 HTTP使用.docx》,实现Webserver的使用。
|
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
2249个成员聚集在这个小组
加入小组灵动微电子MM32全系列MCU产品应用手册,库函数和例程和选型表
11703 浏览 3 评论
【MM32 eMiniBoard试用连载】+基于OLED12864的GUI---U8G2
5930 浏览 1 评论
【MM32 eMiniBoard试用连载】移植RT-Thread至MM32L373PS
10965 浏览 0 评论
【MM32 eMiniBoard测评报告】+ 开箱 + 初探
4577 浏览 1 评论
灵动微课堂(第106讲) | MM32 USB功能学习笔记 —— WinUSB设备
4302 浏览 1 评论
[MM32软件] MM32F002使用内部flash存储数据怎么操作?
981浏览 1评论
806浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-27 22:15 , Processed in 0.540918 second(s), Total 57, Slave 44 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号