APP下载

基于完成端口的文件传输设计

2019-03-30陈李飞

数字技术与应用 2019年12期

陈李飞

摘要:本文主要讨论使用SocketAsyncEventArgs这个类,利用完成端口并且结合异步事件的方式,设计一个服务端的消息传送中心,从而提高服务器端处理高并发的性能,并避免在异步套接字 I/O 量非常大时发生重复的对象分配和同步。

关键词:完成端口;文件传输;套接字

中图分类号:TN915.05 文献标识码:A 文章编号:1007-9416(2019)12-0173-02

1 完成端口简介

“完成端口”模型是迄今为止最为复杂的一种I/O模型。然而,假若一个应用程序同时需要管理为数众多的套接字,那么采用这种模型,往往可以达到最佳的系统性能!但不幸的是,该模型只适用于Windows NT和Windows 2000操作系统[1]。因其设计的复杂性,只有在你的应用程序需要同时管理数百乃至上千个套接字的时候,而且希望随着系统内安装的CPU数量的增多,应用程序的性能也可以线性提升,才应考虑采用“完成端口”模型。要记住的一个基本准则是,假如要为Windows NT或Windows 2000开发高性能的服务器应用,同时希望为大量套接字I/O请求提供服务(Web服务器便是这方面的典型例子),那么I/O完成端口模型便是最佳选择[2]!

在.net中,一旦说到完成端口,我们就不得不提到SocketAsync EventArgs这个高性能的类,其内部是基于完成端口实现的,然后被微软提供了诸多封装,所以使用起来也比较简单一些。由于这个类利用完成端口并且结合异步事件的方式进行设计的[3],所以我们可以大致的知道他的一些特点。

2 处理流程

关于SocketAsyncEventArgs类,微软的解释很多,但是始终离不开高性能三个字。根据我的理解,如果利用此类设计一个服务端的消息传送中心,那么其运作流程如下[1]:

(1)创建SocketAsyncEventArgs池,并且创建缓冲管理中心,负责对池中的对象分配缓冲大小。

(2)创建服务器套接字,并处于监听状态。同时创建基于Socket AsyncEventArgs的客户端接收对象,接收客户端的连接。

(3)如果有客户端连接, 客户端接收对象将会把控制权移交给数据接收对象,数据接收对象开始接收数据。

这只是一个简单的流程,从这里我们可以看出,服务端套接字只是负责监听,一旦有客户端连接,就会把连接事件抛给接收对象;所以客户端一个一个的来,服务端一个一个的抛,性能自然会好了不少。

3 缓冲

说到缓冲,我们很容易理解为一个存储池,里面可以放入东西,也可以拿走。在SocketAsyncEventArgs类中,我们可以利用其SetBuffer方法初始化缓冲区[4]。

比如说:receiveArgs。SetBuffer(new byte[10],0,5);他的意思就是为当前接收数据对象设置的缓冲区大小为10字节,位置从0开始,并且允许接收的最大的数据长度为5字节。

当数据被接收,然后写入到缓冲区的时候,数据会按照预先设定好的缓冲规则进行放置。比如这里我输入aaaaa,那么在缓冲区会放入如下数据:

但是当有新的数据再进来的时候,比如这里我输入了bbbb,那么缓冲区就变成了:

如上图所示,缓冲区中第五位依然是我们前一次插入的值,所以,在这里我提醒大家,缓冲区的东西取完之后,一定要重置一下,否则脏数据会导致数据错误。

讲到这里,也许有人会说,假如我插入aaaaab会怎么样,其实,这个长度已经超过了缓冲区的长度,缓冲区将会做截断处理,然后当作两段放入缓存中,首先会是:

然后会是:

所以如果这个时候你的数据没有被及时取走的话,将会得到最终结果:

这不,已经发生粘包现象了。

4 抛出方式

说完缓冲,这里我们需要说到的是服务端套接字是如何将接收的客户端通过事件的方式抛给SocketAsyncEventArgs对象的。

在进行服务端,我们一般都会有一个用于监听的套接字,套接字会利用serverSocket。AcceptAsync(SocketAsyncEventArgs)异步方法注册SocketAsyncEventArgs对象,然后一旦有客户端连接,就会激发SocketAsyncEventArgs对象的Completed事件,然后,在这个事件中,serverSocket会通过ReceiveAsync(SocketAsync EventArgs)异步方法将数据处理的过程交给另外一个专门负责数据处理的对象去完成,这样,客户端连接,服务端只负责将连接事件抛给SocketAsyncEventArgs对象即可,比起传统的编程方式:服务端既负责监听,又负责接收,效率极大的提升。如图1所示。

5 同步方式

最后说到的是同步问題,因为在异步交互的系统中,同步问题确实很重要,尤其是当客户端和服务器同步的时候。

客户端里面的线程同步,我们可以利用AutoResetEvent来实现,客户端和服务端同步的时候,我们需要AutoResetEvent并且结合一些标记信息来进行,也就是客户端往服务器发送的一些小标记,比如1代表可以进行,0代表取消等等。

在设计的时候,我们还需要记住的是,代码的核心只是负责数据的传输,不要加过多的逻辑判断在里面,否则会影响性能,逻辑判断等最好移到界面处理处来进行。

参考文献

[1] 杨勇.基于完成端口模型的网络服务器性能优化研究[J].科教导刊(下旬),2016(12):35-36+81.

[2] 王允,苏宁.基于完成端口的高性能.Net网络通信服务器模型[J].信息与电脑(理论版),2016(9):23-24.

[3] 李龙.基于Windows的雷达系统操控软件的设计与实现[J].科技信息,2012(21):54-55.

[4] 王璋.基于完成端口模型的大流量服务器开发模式探究[J].福建电脑,2007(2):45-46.

Design of  File Transfer Based on Completion Port

CHEN Li-fei

(Suzhou Higher Vocational and Technical School,Suzhou  Jiangsu  215009)

Abstract:This paper mainly discusses how to use socketasynceventargs to design a message transmission center of the server side by using the completion port and combining with asynchronous events, so as to improve the performance of the server side in dealing with high concurrency and avoid repeated object allocation and synchronization when the amount of asynchronous socket I/O is very large.

Key words:completion port;file transfer;socket