第十九章 TCP Server19.1 TCP Server例程概述 TCP/IP是“transmission Control Protocol/Internet Protocol”的简写,中文译名为传输控制协议/互联网络协议,即网络中(包括互联网)传递、管理信息的一些规范。如同人与人之间相互交流是需要遵循一定的规矩一样,计算机之间的相互通信需要共同遵守一定的规则,这些规则就称为网络协议。在TCP/IP协议族中,有两个互不相同的传输协议: TCP(传输控制协议)和UDP(用户数据报文协议)。 本例程则是将W7500EVB设置为TCP服务器,并通过PC端网络调试助手以TCP客户端的身份向W7500EVB发送连接申请,成功与其建立连接,并能正常收发数据。使用前我们先来了解下TCP协议。 19.2 TCP协议简介 TCP全称是Transmission Control Protocol(传输控制协议),是TCP/IP体系中面向连接的传输层协议,它使用IP作为网络层,提供全双工的和可靠交付的服务。面向连接意味着数据交换在两个建立了TCP连接的特定主机间展开,也就是一对一,所以在TCP通信中不存在多播,广播的概念。 TCP建立通信的两端一端称为服务器端,另一端为客户端。服务器端,指网络中能为用户提供服务的计算机系统,是为客户端服务的;客户端是指与服务器相对应,它是接受服务的一端,为客户提供本地服务的程序。 C/S模型是一个最典型和最常用的通讯结构。实际上,客户和服务器分别是指两个应用程序。客户向服务器发出服务请求,服务器对客户的请求做出相应处理。如图19.2.1所示为一个通过互联网进行交互的C/S模型,此时服务器处于监听客户端连接请求的状态。客户端发出请求,并请求经互联网送给服务器。一旦服务器接收到这个请求,并建立了连接就可以执行请求所制定的任务,并将执行的结果经互联网回送给客户。 图19.2.1 客户/服务器交互模型 19.3 TCP协议通信机制图19.3.1 TCP状态转换图 TCP协议使用中,客户端和服务器端均会处于某种确定的状态,这叫作有限状态机模型。图19.3.1表示了TCP的各种状态之间的迁移转化过程。由于TCP是面向连接的协议,因此在双方数据传输之前,有一个建立连接的过程,即服务器端先进入监听状态,然后由客户端发起建立连接请求;在数据传输完成之后,如果要断开连接,可由任意一方发起断开连接请求。图中粗实线箭头表示客户端的正常状态变迁,粗虚线箭头表示服务器的正常状态变迁。 19.4 TCP连接的建立与断开 TCP协议通过三个报文段完成连接的建立,这个过程称为三次握手(three-way handshake)。TCP连接建立过程如图19.4.1所示。 第一次握手:建立连接时,客户端发送SYN包(seq=j)到服务器,并进入SYN_SEND状态,等待服务器确认。 第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(seq=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 建立一个连接需要三次握手,而终止一个连接要经过四次挥手,这是由TCP的半关闭(half-close)造成的。 第一次挥手:主动方发出设置了FIN位的报文,表示主动终止从本地到远端的单向连接;此时,主动方进入FIN_WAIT1状态,意思就是它在等待远端的FIN报文。 第二次挥手:远端收到FIN后,会立即发送ACK;主动方收到ACK后,进入FIN_WAIT2状态,所以FIN_WAIT1状态持续的时间非常短;此时远端进入CLOSE-WAIT状态,一条单向连接终止了,但另一条还没有,处于HALF-CLOSE连接状态。 第三次挥手:当远端进行了必要的数据发送后,它发送FIN,表示从它出发的单向连接也要关闭;同时它进入LAST ACK状态。 第四次挥手:主动方收到FIN后,回应一个ACK;远端就此进入CLOSED状态,连接关闭;主动方进入TIME WAIT状态;确保最后一个ACK没有丢失,防止新连接占用刚刚关闭的主动方的地址端口,使得网络中旧连接的分组被误认为新连接的分组。
图19.4.1TCP的连接和断开过程 19.5 TCP服务器流程 实现W7500EVB作为服务器的应用。具体操作包括:打开Socket、监听、发送、接收、断开连接以及关闭Socket。与作为TCP客户端不同的操作步骤是监听:在Socket初始化完成后,进入Listen状态。一直等待客户端的连接。先看一下示意图19.5.1。 图19.5.1 TCP服务端模式状态序列
TCP服务器模式流程图19.5.2如下: 图19.5.2 TCP Server流程图 19.6 TCP Server例程解析 了解完了W7500EVB的Socket工作原理和状态迁移过程,我们再来看看实际的程序代码。初始化部分与Network install例程相同,主要区别就是定义了两个变量,即PC机作为服务器的IP地址和端口号。连接过程已经在硬件上实现了,在此就不过多讲解。 uint8 local_ip[4]={192,168,1,25}; /*定义W7500默认IP地址*/ uint16 local_port=8080; /*定义本地端口*/ 这是使用TCP Server例程中建立的服务器IP地址local_ip数组和监听的端口号local_port变量,可以自行修改。如果是使用DHCP自动获取IP地址,则服务器IP地址为获取到的W7500EVB的IP地址。 应用函数int32_t tcps(uint8_t sn)代码如下: - 1. uint8_t buffer[255];
- 2. int32_t tcps(uint8_t sn)
- 3. {
- 4. uint16_t size = 0;
- 5.
- 6. switch(getSn_SR(sn)) /*获取socket的状态*/
- 7. {
- 8. case SOCK_ESTABLISHED : /*socket已初始化状态*/
- 9. if(getSn_IR(sn) & Sn_IR_CON)
- 10. {
- 11. setSn_IR(sn,Sn_IR_CON); /*清除接收中断标志位*/
- 12. }
- 13. if((size = getSn_RX_RSR(sn)) > 0) /*定义size为已接收数据的长度*/
- 14. {
- 15. recv(sn, buffer, size); /*接收来自Client的数据*/
- 16. send(sn, buffer,size);
- 17. printf("%s",buffer);
- 18. if(buffer[0]==0x61)
- 19. flast=1;
- 20. memset(buffer,0x00,size);
- 21. }
- 22. break;
- 23. case SOCK_CLOSE_WAIT : /*socket处于等待关闭状态*/
- 24. disconnect(sn); /*发送socket关闭命令*/
- 25. break;
- 26. case SOCK_INIT : /*socket已初始化状态*/
- 27. listen(sn); /*socket建立监听*/
- 28. break;
- 29. case SOCK_CLOSED: /*socket处于关闭状态*/
- 30. socket(sn, Sn_MR_TCP, local_port, 0x00); /*打开socket*/
- 31. break;
- 32. default:
- 33. break;
- 34. }
- 35. return 1;
- 36. }
复制代码 函数本身也是判断socket状态。首先第29行socket处于关闭状态,进行初始化socket并绑定指定端口。第26行初始化完毕状态则监听指定端口,是否有连接请求。第8行成功建立连接,就会不停判断数据接收缓冲区是否接收到数据,有数据就将数据回发给连接的客户端。 至此,TCP Server例程代码解析就结束了。将TCP Server例程编译烧录后打印串口信息结果如图19.6.1。
图19.6.1 TCP Server例程打印结果 使用网络调试助手,PC机以TCP客户端身份连接W7500EVB,测试是否成功连接并能收发数据。结果如图19.6.2,连接成功,收发数据正常。W7500EVB设置为TCP服务器模式成功。
图19.6.2 TCP Server例程数据交互
|