Select模式下级联文件传输服务器的实现

2020-11-16 06:56邰非林健伟张开骁王国栋
数字技术与应用 2020年9期

邰非 林健伟 张开骁 王国栋

摘要:Select是Windows操作系统提供的一个API函数,它具备强大的网络探测能力且使用方便。众所周知,在阻塞模式下网络通讯可能造成进程挂起,较为可靠的方法是采用非阻塞模式,但Windows底层所提供的socket函数在非阻塞方式下返回值可信度很低,如果通过Select模式结合超时处理来获取返回状态,会大大提升程序返回值的可信度。本文采用java语言来实现一个基于TCP/UDP协议的级联文件传输服务器,其中利用Select模式对端口的可读写性进行探测。通过实际测试,在有效地防止进程挂起的同时能准确获取返回值,从而正确判断端口状态,从侧面增强系统的健壮性与可维护性。

关键词:Select;阻塞模式;非阻塞模式

中图分类号:TP393 文献标识码:A 文章编号:1007-9416(2020)09-0048-03

0 引言

随着互联网的迅猛发展,网络应用已经越来越广泛地融入到各行各业,各种传统设备、业务模式也正向网络化、智能化、集成化方向发展。在其中网络通讯扮演着一个重要且不可缺少角色,但由于各种软、硬件及周边环境等因素的影响,通讯网络上的拥塞情况时常发生,这会造成数据在传输中产生丢包、抖动等现象,从而造成网络性能指标下降。

近几年对网络拥塞问题的研究及提出的解决方案层出不穷,针对具体应用在一定程度上为提升网络性能起到了很好的作用。本文则是通过Windows所提供的Select API[1]函数的功能与特点,结合实际用例,对网络拥塞所造成的函数返回值不稳定性做了进一步的修正,从而给出稳定性、可靠性较高的返回值,为进一步查明网络拥塞原因并给出解决方案提供了技术上的支持。

1 技术路线背景

1.1 Select简介

选择Select可以实现非阻塞式处理方式,此时进程或线程执行此函数时不必等待事件发生,一旦执行肯定返回,其返回值表示函数执行的情况,从中可获取需要监视的文件描述符变化情况即:读写正常或是异常。

Select[1]的函数格式:int select(int maxfdp,fd_set *readfds,fd_set*writefds,fd_set *errorfds,struct timeval *timeout);maxfdp为整型参数,在Unix系统中是指文件描述符的范围,Windows中该参数值可以不设。*readfds结构体指针,用以存放文件描述符即文件句柄,可以是普通文件也可以是设备、管道、FIFO,主要提供读状态变化。*writefds指针变量则是负责文件句柄写状态获取。*errorfds为记录异常状态的结构体指针。timeval结构体指针代表以秒或毫秒计量的时间值,这个参数至关重要,它可以使select处于三种状态:(1)赋值NULL时是将Select置于阻塞状态。(2)赋值为0时表示纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值。(3)赋值大于0则为超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。

1.2 基于Select的服务器架构与流程

图1所示为级联服务器和客户端的物理部署图,为了简单起见,此处只给出了一个客户端连接状态,各级服务器上运行的服务进程是相同的,它们之间通过TCP[2-3]连接。客户端与服务器端下载文件通道则使用UDP[2-3]。

图2给出了文件查找和传输的流程,服务器首先要进行初始化,客户端发起下载文件请求给第一个级联服务器,该服务器查询本地文件,如果有则推送文件,如果没有则转发到下一级级联服务器,依此类推直到最后一级级联服务器,如果没有查到文件则仍依次将错误信息返回给客户端。

在服务器与服务器以及服务器与客户端之间通讯中,我们采用了Select模式去探测可能出现的各种通讯故障,通过返回值及时给出应对处理。部分关键代码[4]如图3所述。

2 实现算法描述

文件服务器有三个通讯端口:P、P+1、P+2。服务器启动时P端口进行UDP[2-3]监听,主要负责接收查询字符协议。P+1进行TCP[2-3]监听,用以维护服务器间的连接。P+2进行UDP[2-3]监听,响应自客戶端的初始化通知。

考虑到客户端是不断变动的,此处用UDP监听是利用其无状态特性,如果用TCP则会出现TIME_WAIT,每四分钟才可重新连接,效率极低。P+1和P+2端口只要其中一个收到上一级服务器的初始化数据包,另一个则会自动关闭,从而节省资源。对于中间(非最后)服务器和客户端则需要在启动和查寻时通知下一级服务器,客户端利用UDP协议连接下一级服务器的P+2端口,服务器用转发端口连接下一级服务器的P+1端口。所有服务器初始化完成后,一个通畅的文件传输网络就构建起来[5]。

客户端请求发出到服务器上,服务器将查找本地共享目录中是否有该文件。没有则将查找请求发送到自己的下一服务器。如果有该文件则发送文件到客户端。对于非第一服务器,如果有该文件将会把结果发送到上服务器的TEMP端口,而TEMP端口继续转发直到客户端。而当查找请求到最后服务器时,还没有该文件,将返回字符串“wrong!”到上一服务器的TEMP端口,直到服务器,服务器会给出找不到该文件的提示。

图4中给出了客户端、中间服务器、终端服务器关键线程调用时序图[6],客户端设置了两类超时,一是初始化通讯超时,另一个则为接收文件超时,主要用以提高交互的效率。服务器端则提供更新实际存储文件服务器IP地址的线程服务,也是基于效率考虑的。

3 结语

在文件服务器与客户端程序中使用Select实时对网络的通讯状态进行监控,有利于及时获取网络状态,以便做更进一步的优化扩展。本文中将这种便捷用于文件传输服务器上,从实际使用效果来看能很好地应对网络异常情况下的策略调整,当然程序还有进一步优化的空间,另外这种模式也可以用在其它复杂环境下的网络通讯程序之中。

参考文献

[1] Jeffrey Richter.Windows核心编程(第5版 中文版)[M].北京:清华大学出版社,2008.

[2] W.RICHARD STEVENS.TCP/IP Illustrated Volume 1(The Protocols)[M].北京:机械工业出版社,2005.

[3] 孙晓刚.面向软件工程的Visula C++网络程序开发[M].北京:清华大学出版社,2004.

[4] BJARNE STROUSTRUP.The C++ Programming Language(special Edition)[M].北京:高等教育出版社,2003.

[5] Martin Fowler.重构:改善既有代码的设计(中文版)[M].北京:中国电力出版社,2006.

[6] James Rumbaugh.The Unified Modeling Language Reference Manual[M].the United States of America:Addison Wesley Longman,Inc,1998.