一种支持多客户端的TCP服务器模型

2019-09-09 13:33罗显庭黎艳群
数码世界 2019年6期
关键词:调用线程监听

罗显庭 黎艳群

摘要:TCP服务器程序在现今网络发达的仪器仪表中应用广泛。本文以降低设计人员开发难度为目的,从模块化的设计思想出发,提出一种支持多客户端的TCP服务器模型。

关键词:TCP服务器单线程多客户端类 回调函数

在嵌入式仪器仪表中,经常会遇到需要通过TCP和第三方设备进行通信。开发人员每天忙碌在重复繁琐的编码工作中,为仪表编写不同的应用层协议以适配现场的工作需要。虽然编写TCP服务器程序有很多种形式,例如为每个客户端fork出单独的进程或者为每个客户端创建单独的线程,这样势必增加系统的开销,占用过多的资源。本文从通用性和可移植性等方便考虑,实现一种支持多客户端的TCP服务器模型,减少后期代码的重复编写。

TCP服务器模型首先抽象为类的方式,具体数据的实时处理则交由回调函数去完成,将数据收发和协议解析部分分离,减轻开发人员的编码工作、增强程序的稳定性。

抽象出的类主要有以下几个方法:服务器打开、关闭、线程启动、数据发送和接收等,具体实现接口如下

服务器打开方法Open:

该方法主要用于定义监听服务器的IP地址和端口号,同时设置为非阻塞模式以及限制最大连接数量。调用成功返回服务器的套接字句柄,否则返回无效句柄。具体实现流程如下:

服务器关闭方法Close

主要用来关闭已连接或未释放的客户端套接字,同时在应用程序退出前关闭服务器自身用于监听的套接字。

客户端数据发送的方法SendData

此方法由两个函数组成,一个函数用于在已经连接上的客户端队列中搜索,当前是和哪个客户端套接字进行数据通信。另一个函数直接向对应的套接字发送数据(注意在搜索套接字、发送数据失败时需做重发或关闭等异常处理)。

服务器线程启动方法StartThread

该方法主要用来定义两个回调函数,一个用于通知客户端已连接的事件,另一个用于通知客户端已接收到数据的事件。同时创建一个线程,用于服务器接受连接、客户端的数据接收和关闭等操作。

服务器接收连接或客户端数据接收的方法ThreadFun

该方法主要实现不断地监测服务器监听端口是否有新的接收连接,已连接的客户端是否有数据发送过来,以及是否有客户端申请关闭断开等操作。

在一个线程中实现多个客户端连接和服务器监听功能,主要使用到了select系统调用。Select系统调用允许程序同时在多个底层文件描述符上等待输入的到达。这意味着服务器可以同时在多个打开的套接字上处理多个客户端的请求动作。具体处理流程如下:

服务器让select同时指向检查监听套接字和客户的连接套接字的Fd_set集合,通过用select调用同时处理多个客户就不需再依赖多进程或多线程了。一旦select有活动发生,就可以用FD_ISSET来遍历所有可能的文件描述符,以检查是哪个套接字有活动发生。

如果是监听套接字可读,这说明当前有一个客户试图建立连接,此时就可以调用accept而不用担心发生阻塞的可能,同时利用客户端连接回调函数通知应用层有新的客户连接。

如果是某个客户描述符准备好,说明该描述符上有一个客户请求需要我们读取和处理。如果读操作返回零字节,表示有客户已结束,就从客户端隊列中搜索关闭对应的套接字,并把它从文件符集合中删除。如果返回的数据大于零,就直接读取数据,同时通过客户端数据接收回调函数将接收到的数据通知上层进行数据解析和处理。

模型的实例化使用整个操作如下,定义一个服务器对象,打开对应的监听端口号,定义两个回调函数,启动线程处理函数。

在上层的调用程序中只要定义两个回调函数就可以,tcp_accept函数实现有新客户连接需要处理的功能,custom_recv函数实现客户端数据接收时需要进行的数据解析和处理功能即可。

在实际的工程应用中,此模型可以监听多个设备获取不同设备的运行状态数据,功能强大。采用尽量少的线程数量和限制客户端的连接数量,系统开销小。同时采用非阻塞模式防止程序干扰其他设备的请求响应,响应快速。TCP服务实现和协议解析部分分离,代码可移植性强,性能稳定。

参考文献

[1]陈健、宋健健译.《Linux程序设计》(第3版)人民邮电出版社.

猜你喜欢
调用线程监听
基于Android Broadcast的短信安全监听系统的设计和实现
Java多线程产生安全问题及对策分析
采用ScheduledThreadPoolExecutor执行定时重试任务时内存溢出的分析及解决
监听“有”道 ——杰夫(美国)
利用RFC技术实现SAP系统接口通信
论秘密监听的立法问题
C++语言中函数参数传递方式剖析
Java的多线程技术探讨