特权同学

以太网,FPGA就一定能搞定之TCP客户端模式传输实例--上

0
阅读(4764)

以太网,FPGA就一定能搞定之TCP客户端模式传输实例--

以太网,FPGA就一定能搞定系列之UDP传输实例

本系列博文节选自特权同学的FPGA开发电子书《SF-CY3 FPGA套件开发指南》。

最新设计文档下载地址:http://pan.baidu.com/s/1em79m

1 概述

本实例的硬件系统和前面的实例一样,只是在CH395芯片的应用上使用了不同的传输模式。本实例要传输的是TCP协议的IP包,只要设置CH395工作于TCP模式,作为客户端设置好目的IP地址和收发端口号,不断尝试进行TCP连接的建立。在和服务器端成功建立连接后,就可以正常收发数据包了。通过这个实例大家可以初步掌握TCP协议的传输和格式。

2 TCP协议解析

TCP要比UDP来得可靠,但与UDP通信的简单高效不同,TCP相应的要付出更多的资源来获取更可靠的传输。如TCP协议进行有效数据传输前需要进行多次握手建立连接,结束传输后也需要多次握手断开连接,在传输过程中还有超时重传和捎带确认等机制用于保证数据包的有效传输。此外,由于以太网本身是个多点通信的总线,TCP协议对于流量控制和拥塞控制上也都有相应的约定和算法支持。

TCP是一种可靠的、面向连接的字节流服务。源主机在传送数据前需要先和目标主机建立连接。然后,在此连接上,被编号的数据段按序收发。同时,要求对每个数据段进行确认,保证了可靠性。如果在指定的时间内没有收到目标主机对所发数据段的确认,源主机将再次发送该数据段。TCP帧协议格式如图所示。

TCP的连接如图所示,需要使用三次握手协议建立连接。当主动方(通常是客户端)发出SYN连接请求后,等待对方回答SYN-ACK。第一次握手:建立连接时,客户端发送SYN包(SEQ=x)到服务器,并进入SYN_SEND状态,等待服务器确认。第二次握手:服务器收到SYN包,必须确认客户的SYN(ACK=x+1),同时自己也送一个SYN包(SEQ=y),即SYN+ACK包,此时服务器进入SYN_RECV状态。第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ACK=y+1),此包发送完毕,客户端和服务器进入Established状态,完成三次握手。


● 源、目标端口号字段:占16比特。TCP协议通过使用“端口”来标识源端和目标端的应用进程。端口号可以使用065535之间的任何数字。在收到服务请求时,操作系统动态地为客户端的应用程序分配端口号。在服务器端,每种服务在“众所周知的端口”(Well-Know Port)为用户提供服务。

● 顺序号字段:占32比特。用来标识从TCP源端向TCP目标端发送的数据字节流,它表示在这个报文段中的第一个数据字节。

● 确认号字段:占32比特。只有ACK标志为1时,确认号字段才有效。它包含目标端所期望收到源端的下一个数据字节。

● 头部长度字段:占4比特。给出头部占32比特的数目。没有任何选项字段的TCP头部长度为20字节;最多可以有60字节的TCP头部。

● 标志位字段(UAPRSF):占6比特。各比特的含义如下:
URG:紧急指针(urgent pointer)有效。
ACK:确认序号有效。
PSH:接收方应该尽快将这个报文段交给应用层。
RST:重建连接。
SYN:同步位,发起一个连接。
FIN:终止位,释放一个连接。

● 窗口大小字段:占16比特。此字段用来进行流量控制。单位为字节数,这个值是本机期望一次接收的字节数。

TCP校验和字段:占16比特。对整个TCP报文段,即TCP头部和TCP数据进行校验和计算,并由目标端进行验证。

● 紧急指针字段:占16比特。它是一个偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。  

● 选项字段:占32比特。可能包括“窗口扩大因子”、“时间戳”等选项。

3 TCP连接的建立和断开

TCP的连接如图所示,需要使用三次握手协议建立连接。当主动方(通常是客户端)发出SYN连接请求后,等待对方回答SYN-ACK。第一次握手:建立连接时,客户端发送SYN包(SEQ=x)到服务器,并进入SYN_SEND状态,等待服务器确认。第二次握手:服务器收到SYN包,必须确认客户的SYN(ACK=x+1),同时自己也送一个SYN包(SEQ=y),即SYN+ACK包,此时服务器进入SYN_RECV状态。第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ACK=y+1),此包发送完毕,客户端和服务器进入Established状态,完成三次握手。


断开连接的示意如图所示。当主动断开的一方发送FINfinish)报文给对方,也就是一个设置了FIN标志位的报文段。FIN报文也可能附加用户数据,如果这一方还有数据要发送时,将数据附加到这个FIN报文是完全正常的(ACK报文也有可能出现类似的捎带现象,这也是提高数据传输效率的好办法)。

当被动关闭的一方收到FIN报文时,它会发送ACK确认报文。因为TCP是双工的,也就是说,一对TCP连接上有两条数据通路。当发送FIN报文时,意思是说,发送FIN的一端就不能发送数据,也就是关闭了其中一条数据通路。被动关闭的一端发送了ACK后,应用层通常就会检测到这个连接即将断开,然后被动断开的应用层关闭连接。与此同时,被动关闭的一端也发送FIN给主动关闭端。有时候,被动关闭端会将ACKFIN两个报文合在一起发送。主动关闭端收到FIN后也发送ACK,然后整个连接关闭,四次握手完成。由于被动关闭端可能会将ACKFIN合到一起发送,所以这也算不上严格的四次握手,或者可以称之为四个报文段。

4 TCP客户端模式介绍

TCP客户端模式收发数据的对应数据流如图所示。在初始化时,需要设定目的IP地址、目的地端口号和源端口号,同时需要发送命令建立TCP的连接。在TCP连接建立完成后,就可以进行正常的TCP数据包的收发通信了。

TCP提供面向连接的,可靠的字节流服务。TCP连接建立后,可以进行数据收发。在连接未建立前不得进行数据发送操作。

FPGACH395写入若干字节数据流后,CH395数据流封装在TCP数据部分进行发送。TCP一包可以发送的最大长度为800字节,如果FPGA写入的数据流长度大于800字节,CH395会将数据流封装成若干个TCP包进行发送且每包成功发送后都会产生SINT_STAT_SEND_OK中断。FPGA每次写入的字节长度不得大于发送缓冲区长度(2KB),且收到SINT_STAT_SENBUF_FREE中断后才可以进行下一次写数据操作。在TCP模式下,如果数据发送失败会产生SINT_STAT_TIM_OUT中断,CH395会自动将此Socket关闭。

CH395接收到TCP报文后,将TCP数据复制到Socket接收缓冲区中并产生SINT_STAT_RECV中断,FPGA收到此中断后,可以发送命令CMD_GET_RECV_LEN_SN来获取接收缓冲区数据的长度,然后发送命令CMD_READ_RECV_SN来读取缓冲区的数据。FPGA可以一次将所有数据读出也可以只读出部分数据,接收缓冲区剩余空间即为TCP的窗口,FPGA每次读数据后,CH395会对接收缓冲区的剩余空间进行检查并向TCP服务器通告当前窗口的大小。

5 软件设计

本实例软件流程如图所示。TCP客户端模式设置中需要设置目的主机的IP地址,即PC机的IP地址192.168.1.103;并且设置源端口号和目的端口为634010进制)。随后不断尝试和服务器建立连接,建议大家可以事先打开PC端的TCP调试工具,设置好相关参数,使其运行于服务器模式,一旦我们运行该实例软件,则客户端与PC的服务端将建立连接。此后,客户端进入主循环,等待服务器发送数据后产生中断。一旦客户端接收到服务端发送的数据,则打印接收数据,将所有数据取反后发回给PC机。

软件代码请参考例程。

Baidu
map