Canoe CAPL语言实现TCP连接与通信流程
一、前期准备
本文主要讲解CAPL语言里是如何实现TCP连接通信的,所以在本文开始前需要一些前期准备。
1、首先是需要了解TCP的报文格式,连接三次握手,断开连接四次挥手的相关知识,推荐以下两位博主文章。
2、Canoe自带实现TCP连接的CAPL例程,以及在帮助文档里有对TCP接口进行相关的说明,本文以例程为例,对逻辑进行梳理,进行相关更改。
例程路径:C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 16.0.145\Ethernet\Simulation\TCPBasicCAPL
说明文档路径:Ethernet>TCP/IP API
3、在说明文档里可以看到创建客户端和服务端套接字流程以及TCP API函数的使用说明。
先了解下简要流程,具体函数使用往后继续讲解。
在客户端,需先使用TcpOpen创建一个Socket(套接字)绑定地址和端口,TcpOpen函数创建完端口后,会返回一个句柄,这个句柄可供后续相关TCP的API函数使用。然后使用TcpConnect函数便可将创建的客户端Socket向目的地址和目的端口(服务端Socket)发起连接。
在服务端,也是使用TcpOpen创建一个Socket。而服务端还需使用TcpListen监听函数,来等待连接,如果收到连接请求,会回调OnTcpListen函数,在OnTcpListen函数里需要使用TcpAccept函数对连接请求进行接受,TcpAccept函数在接受请求后会重建一个新的Socket用于连接通讯。也就是服务端会有两个端口,一个是服务器端口,用于接收连接请求,一个是连接端口,用于连接建立好后进行与客户端的通讯。
而端口的关闭均使用TcpClose函数。
二、TCP连接流程实现
1、打开工程
我们打开示例工程看看是如何进行TCP连接模拟的。
首先看到Setup桌面面板,有两个节点分别是Server和Client。Start Value里是对一些变量的值初始化。
接着看到Simulation桌面面板,里面有Server和Client两个操作面板。
2、运行演示
先看下Start Value面板里的赋值顺序,Listen赋值为0,Connect赋值为0,TxText初始化会“Hello World”,RxText初始化清空。点击闪电Start图标运行,可以看到Listen键置灰,Connect键置灰,TxText文本框里有“Hello World”字符串,点击Send发送,原本清空的RxText框收到了“Hello World”字符串。并且在trace窗口,可以看到tcp三次握手连接的报文以及传输“Hello World”字符串发送和应答报文。
3、代码对应
根据运行演示的步骤,来具体看看CAPL代码里的实现。
首先看看按下服务端按下Listen按键触发的操作。
TCP栈的位置,以及客户端和服务端ip地址的设置。
服务端开启监听后,客户端Connect按键按下发起主动连接。
客户端用了Connect函数后便会发送连接请求,收到服务端的第一帧应答后,也就是第二次握手后,接着会触发OnTcpConnect函数。
第三次握手后,会触发OnTcpListen监听函数,创建一个新的连接socket进行通信。
连接完成后,服务端点击send按钮进行发送,触发相关事件,并用连接socket进行消息的发送。
在服务端发送信息后,则会触发客户端接收回调函数的使用,进行消息的接收。
最后再看看关闭函数,就是直接调用close函数,服务端close会触发客户端回调OnTcpClose,客户端close会触发服务端回调OnTcpClose。
4、客户端向服务端发送消息
源码里已经有服务端向客户端发送消息的代码了,那客户端怎么向服务端发送消息,直接用客户端socket调用send函数就可以了,因为连接已经建立好,所以不用指定服务端的连接socket。
服务端在OnTcpReceive函数里对接收数据进行处理。
补充:
CAPL提供两种API的使用方式,如下图,一种是函数形式,一种是方法形式。上面例子均使用的是方法形式,即定义了一个TcpSocket的数据类型gSocket,直接用gSocket这个数据对象去调用send函数或其他函数。
如要使用函数形式,则需要先用TcpOpen函数先创建一个socket,TcpOpen会返回一个dword数据类型的句柄,在使用其他函数时侯,如下方TcpSend时,将句柄传入dword socket这个参数即可,其他函数类似。在程序编写时,使用其中一种形式进行编写较为便利。
三、总结
以上,capl里实现tcp连接通讯流程是,client和server用open()打开创建socket,服务端用listen()监听,客户端用connect()去主动连接,服务端在listen()回调里用accept()接收连接请求,并创建一个新socket,完成连接,最后用send()即可互相通讯。而close()用于关闭连接。用好open()、listen()、connect()、accept()、close()、send()函数则tcp的三次握手、四次挥手程序自动会去实现。