CVI基于TCP的C/S例程学习心得

欲看图文版,请PC浏览器下载附件pdf。

我想实现两个exe之间的信息互通,豆包说用TCP,遂开始学习CVI2010 TCP的例程。

遗憾的是,CVI例程向来缺乏参考文档,于是用户极不容易入门原厂例程。尤其是TCP这样的例程,本来就牵涉了一个晦涩的网路通信协议,理解例程就需要同时开两个或两个以上的project,作为主从机对着干才有实效。我于是瞎蒙了两天,终于try出来一些名堂,并写成文档,供后来者快速理解。

一、 学习TCP/IP例程Message.cws

1, 找到CVI2010的TCP/IP例程Message.cws入口

该例程Message.cws在我笔记本上的完整路径名是C:\Users\Public\Documents\National Instruments\CVI2010\samples\tcp\Message.cws。下面是通过CVI的起始页面,搜索原厂例程的步骤。

2, CVI打开Message.cws

可见一个cws里面,包含了两个project,分别是Message,和MessageReader。由于Message是加粗了的,所以是当前激活的project,在CVI中直接运行的将是MessageWriter.c对应的exe。

这里我们还需要运行MessageReader.c对应的exe,就必须再运行一个CVI并打开Message.cws,然后鼠标右键点击MessageReader,选"Set Active Project",之后这个MessageReader就变粗体了,成为当前project。

3, CVI运行Message.cws,从server端传数据到client端

豆包说,在该例程里,MessageReader是客户端,MessageWriter是服务器,所以两个exe的启动顺序是由讲究的,必须先运行服务器MessageWriter的exe。

如何区分哪个程序是Client,哪个程序是Server呢?豆包说应以代码里的实际函数为准:

谁调用了StartTCPServer(启动监听),谁就是服务器,就必须先启动;

谁调用了ConnectToTCPServer(发起连接),谁就是客户端,就必须后启动。

如果,我们错误地首先运行了客户端的MessageReader的exe,就会在运行到ConnectToTCPServer()函数时报错,Timeout error:

所以得老打老实地先运行服务器MessageWriter的exe,后运行客户端的MessageReader的exe,两个exe才能愉快地玩耍:

您观察得很敏锐!两个GUI背后的CMD黑窗,应该跟CVI的exe没有直接关系。但是为什么我会一起截屏呢?这是因为,我最开运行客户端的MessageWriter的exe,其界面上"Send Date"按键是失活的,不晓得为啥,例程源码中也没有说明,甚至没有提及应该首先运行哪个exe呢。不由得感慨------很多时候,一个工程师如果没有第三方的支援,就会卡死在万里长征的第一步。

还好有诲人不倦的豆包啊,豆包说有可能是其他进程已经率先占用了端口号10000,导致同样使用端口号10000的MessageWriter无法启动TCP服务器。于是我就按照豆包说的,输入查看端口10000是否被占用的指令:netstat -ano | findstr 10000,结果如下,果然是有个进程已经占用了本机10000号端口。然后还可以根据端口号输入指令tasklist | findstr xxxxx,来反查是哪个软件进程占用的,居然是百度云盘。

豆包说,要么把这个进程用任务管理器杀掉,要么修改CVI例程的端口号,从10000改到10001。两种方案我都试过了,都OK。前面黑窗背景的图就是杀掉YunDetectService.exe之后再运行例程的结果,下图是修改CVI例程源码的端口号到10001之后再运行的查询结果:

其中,

进程 ID 4188 是MessageWriter_dbg.exe(服务器端),它已经成功监听了10001端口(LISTENING表示服务器在等待连接)。

进程 ID 8756是MessageReader_dbg.exe(客户端),用临时端口 63310。

二、 学习TCP/IP例程 server.cws和client.cws

该例程是基于 TCP/IP 协议的客户端 - 服务器(C/S)通信经典例程,核心演示了如何利用CVI的 sockutil 库实现跨进程/跨设备的网络数据交互。

该例程在我笔记本的文件路径是C:\Users\Public\Documents\National Instruments\CVI2010\samples\tcp\server.cws和client.cws。下面是通过CVI的起始页面,搜索原厂例程的步骤。

先后运行server.cws和client.cws,当用户往文本框输入一条字符串之后回车,会发送到另一侧并显示出来:

Server.c解析

注意到,开篇#include <tcpsupp.h>,这是CVI专属TCP通信支撑库(RegisterTCPServer/ServerTCPRead等核心API)。

函数RegisterTCPServer (portNum, ServerTCPCB, 0) 是注册 TCP 服务器的核心API。其中,portNum是端口号比如10000,ServerTCPCB是回调函数。该函数的作用是让程序在指定端口监听客户端连接,并绑定 "TCP事件回调函数ServerTCPCB"------ 即后续所有 TCP事件(客户端连接、数据收发、断开)都通过该回调函数来响应。

函数ServerTCPWrite (g_hconversation, transmitBuf, strlen(transmitBuf), 1000) 是向已连接的TCP客户端发送数据的核心API,专门用于服务器端向客户端写入数据流。

函数dataSize = ServerTCPRead (g_hconversation, receiveBuf, dataSize, 1000) 是服务器端读取客户端发送数据的核心 API,负责从已连接的TCP客户端接收数据流。该函数一般是放在回调函数ServerTCPCB中被TCP_DATAREADY事件触发所调用。

UnregisterTCPServer (portNum) 是注销 TCP 服务器的核心API,是 RegisterTCPServer 的 "反向操作"------ 用于停止服务器对指定端口的监听、释放底层套接字资源、注销 TCP 事件回调。

Client.c解析

函数ConnectToTCPServer (&g_hconversation, portNum, tempBuf, ClientTCPCB, NULL, 5000) 是 TCP 客户端主动连接服务器的核心API,用于客户端程序向指定 IP+port的TCP服务器发起连接请求,并绑定客户端的TCP事件回调函数ClientTCPCB。

函数dataSize = ClientTCPRead (g_hconversation, receiveBuf, dataSize, 1000) 是 TCP客户端读取服务器发送数据的核心API,负责从已建立的 TCP 连接中接收服务器下发的流数据。该函数一般是放在回调函数ClientTCPCB中被TCP_DATAREADY事件触发所调用。

函数ClientTCPWrite (g_hconversation, transmitBuf, strlen(transmitBuf), 1000) < 0 是TCP客户端向服务器发送数据的核心API,负责将客户端缓冲区的数据通过已建立的TCP连接发送给服务器。

三、 学习TCP/IP例程 MultiClientServer.cws

CVI2010的MultiClientServer.cws例程是一个典型的多客户端TCP服务器演示程序,主要功能是展示如何实现一个服务器同时与多个客户端建立TCP连接并进行通信。其中,服务器端(Server):作为TCP服务器,启动后监听指定端口(如默认的5000),支持同时接收多个客户端的连接请求,并为每个客户端创建独立的通信线程。客户端(Client):可同时启动多个实例,每个客户端通过TCP协议连接到服务器,实现与服务器的双向数据交互。

该例程特点如下:

多客户端并发连接:服务器通过线程池(Cmt函数库)管理多个客户端连接,避免单个客户端阻塞其他连接,支持同时处理多个客户端的请求。

双向数据通信:客户端可向服务器发送数据(如文本、数值等);

服务器接收后可实时响应(如返回确认信息、处理后的数据),并支持向指定客户端或所有客户端广播消息。

连接状态管理:服务器实时显示已连接的客户端信息(如客户端IP、端口、连接时间),支持主动断开某个客户端连接;客户端也能显示与服务器的连接状态。

异常处理:包含连接超时、客户端异常断开、网络错误等场景的处理逻辑,确保服务器稳定运行。

总的来说,该例程的核心价值是展示CVI中TCP多连接处理和线程并发编程的最佳实践,代码中包含了服务器监听、客户端连接、多线程数据收发、连接管理等关键逻辑,适合作为开发多客户端通信系统的参考模板。

该项目在我笔记本上的完整路径是C:\Users\Public\Documents\National Instruments\CVI2010\samples\tcp\MultiClientServer.cws。下面是通过CVI的起始页面,搜索原厂例程的步骤。

刚才试通了一主多从的TCP通信的例程,没有参考文档就纯粹靠瞎蒙了。这里需要开三个CVI,分别打开MultiClientServer.cws、和两个client.prj。

老规矩,先运行server即MultiClientServer.cws。初始界面这样的,很多控件都是失活的,等待client上线:

然后在默认的debug模式下运行第一个client.prj,显然server这边侦听到有一个client上线了,客户端名称列表框就多了一行记录,同时还会弹出一个窗口Message from Client出来:

然后手动修改成release模式运行第二个client.prj,可见server这边就一共侦听到两个client上线,客户端名称列表框就有了两行记录。同时再弹出一个窗口Message from Client。这里手动把两个client界面和两个Message from Client弹窗都摆好位置:

然后用户就可以尝试双边通信了:

所以我上午的设想的,一个Server.exe配合4个ATE.exe去控制一台4通道OpticaslSuit,应是完全可行的了?

相关推荐
zbtlink2 小时前
专业路由器 vs 电脑软件WiFi,差异在哪?
网络·智能路由器
wanhengidc2 小时前
云端虚拟 巨椰 云手机
运维·服务器·安全·智能手机·云计算
wanhengidc2 小时前
云手机 互联网 云端科技
运维·服务器·科技·智能手机·云计算
ChristXlx2 小时前
Linux安装Minio(虚拟机适用)
linux·运维·网络
华纳云IDC服务商2 小时前
服务器被DDOS跟CC攻击了怎么处理,如何抵御攻击?
服务器·网络·安全
A13247053122 小时前
Linux文件查找:find和locate命令入门
linux·运维·服务器·网络·chrome
咕噜企业分发小米2 小时前
阿里云与华为云服务器哪个更利于人工智能?
服务器·阿里云·华为云
飞机火车巴雷特2 小时前
PyCharm通过跳板机连接隔离内网服务器
运维·服务器
yenggd3 小时前
华为sr-mpls TE配置案例
网络·华为