完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
上一节我们对TCP的报文和连接过程做了介绍,本节通过Socket的方式对整个通信过程再次进行一次整理(使用Socket方式易于加深对以太网通信过程的理解,在此讲解使用的是完整版Socket)。
服务器端初始化 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段后也断开连接 各个信号引脚对应如下: 从名称中就可以看出函数功能用于设置套接字的一些选项,我们关注一下参数: (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 #define IP_ADDR0 192 #define IP_ADDR1 168 #define IP_ADDR2 105 #define IP_ADDR3 26 将程序下载入开发板中,使用NetAssist进行如下设置: 1)协议设置,此时设备为Server,则PC为Client 2)设置远程主机地址(即设备地址) 3)端口号
通过上图可以观察到发送成功,并且设备返回数据与发送数据一致,表明实验成功。
实验程序请登录我们的官网(http://www.mindmotion.com.cn/download.aspx?cid=2542&page=2)下载MM32F3270 SDK,工程路径如下: ~MM32F3270_Lib_Samples_V0.90Demo_appEthernet_DemoETH_RTOSFreertos_Server_socket 我们下节的题目为《基于MM32F3270以太网UDP_socket使用》。 |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
2252个成员聚集在这个小组
加入小组灵动微电子MM32全系列MCU产品应用手册,库函数和例程和选型表
11817 浏览 3 评论
【MM32 eMiniBoard试用连载】+基于OLED12864的GUI---U8G2
5975 浏览 1 评论
【MM32 eMiniBoard试用连载】移植RT-Thread至MM32L373PS
11115 浏览 0 评论
【MM32 eMiniBoard测评报告】+ 开箱 + 初探
4594 浏览 1 评论
灵动微课堂(第106讲) | MM32 USB功能学习笔记 —— WinUSB设备
4326 浏览 1 评论
[MM32软件] MM32F002使用内部flash存储数据怎么操作?
1271浏览 1评论
846浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 05:31 , Processed in 0.579269 second(s), Total 52, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号