Wu.Country@侠缘

勤学似春起之苗,不见其增,日有所长; 辍学如磨刀之石,不见其损,日所有亏!

导航

给IIS服务器添加Socket的设想及几个解决方案。

我没想到可以直接在IIS里用Socket编程,这为我的项目添加了不少活力。大家应该知道,一但我可以在IIS里新建立一个Listen,还有什么不能做呢?

首选还是给出需求:大文件上传,保证可以断点上传!且记录上传日志。
前面好些文章已经讨论过,HTTP协议下是没有办法进行断点上传,所以用HTTP协议来解决这一问题是不用想了。
那么我们可以讨论的还有:CTP/IP,SOAP等几个可用。当然,可能还有其它的我不知道,也就不说了。
先说SOAP协议下的文件上专,前面我做一了个小项目,进行过测试,在基于HTTP协议下的WebService可以断点上传大文件。可以参考下文,有源文件下载:
http://www.cnblogs.com/WuCountry/archive/2006/02/15/331248.html

然而在实际使用中,它的问题太明显了:效率极低。
在LAN里上传文件还可以接受,速度也还可以,但在Internnet上进行上传文件时,经常出现超时情况,几乎无法上传文件。因为WebService的每一个函数调用都有返回,如果上次调用没有返回那么就不能进行第二次的调用(否则文件混乱)。而因为网络不稳定的情况下,大部份时间消耗在来回的调用上,而不是数据的传输。例如:每次调用上传10K的数据,根据不同的网络情况,客户端等的时间不一致,大概是60秒左右,如果没有返回,那么不得不重新调用函数检查服务器上文件的大小重新上传,并减小上传数据。最后一至到1K,结果还是有超时,当然相对会少一些。也可以适当的延长超时的时间,但不管怎样,最后平均算下来的上传速度十再是不敢恭维。
然而这一解决方案也并不是完全无可取之外,在网络环境极好的情况下,它的效率还是可以的,而且实现也简单,再加上MS强大的WebService技术支持,升级及维护也简单。所以我个人还是很喜欢这样的解决方法的。如果不是因为网络环境的约束,我还真想就用这个方案。

另一个方法就是用TCP/IP直接用Socket连接来上传文件。它的上传效率与FTP是一致的,因为FTP也是用的TCP/IP协议,因此,完全可以考虑在网络环境不好的情况下用这一解决方案。然而它的不利之处就是:服务器的架设。其实服务器端的代码完全可以说是一个FTP的架构了,就看你实现多少命令。且不管这些,如果在IIS服务器启动这一服务,里采用这一方案的核心问题。首先,把服务器端与客户端的程序都写好,服务器端写成组件的形式,方便下面的部署。当然,如果你把服务器端的也写成UI程序,然后在服务器上启动它也行,然而我就是想让它与IIS绑定在一起,最后是与有的ASP.net应用程序绑定。
好了,我还是决定用组件的形式来完成。它有一个好处,就是在部署时有更多的选择。先看在ASP.net应用程序里的部署。
因为只用在服务器上开一个监听端口就行了,所以直接配置Config文件,指定IP与端口。然而在Global里启动它。因为只用启动一次,所在放在静态构造函数里就行了。

        static Global()
        
{
            
//
            if(Global.M_WaveUpService==null)
            
{
                Global.M_WaveUpService 
= new WaveUpService();
                Global.M_WaveUpService.M_SystemVideoPath 
= Global.M_SystemPath;
                Global.M_WaveUpService.StartWaveUpService();
            }

        }


然而这样的问题是:如果IIS出现错误,导致服务停止,再由谁来启动服务呢?这是很头疼的问题。必须重新请求一次页面能让服务重新启动。这是我不想看到的。
而且如果因为服务出现问题,而不是IIS,也就是说,就算我重新请求了页面,而这个静态的Global也不一定执行时,那就先郁闷了。有一个解决方法就是重新写一个管理页面来完成服务器的管理。而这样就更麻烦了,谁会因为服务不能运行而登录到网站重新启动服务呢?而且服务也只有管理员才能管理。所以,这样的一个方法在试运行了几天后,放弃了。

如果要让服务可以长期稳定的运行,除了前面的方法写一个UI程序来运行外,还有一个解决方法就是做Windows服务(详细的可以在MS上查找Windows Service得到更多的帮助)。这一解决方法我觉得很不错,它就像是在服务器上安装了一FTP服务一样,当然它只为你个人的服务运行。这是一个备选方案,它唯一不好的就是更新,要重新安装与测试。而且要有自己的服务器。

想在IIS上直接启动服务,还有一个方法就是借助WebService来启动及维护服务,然后用Socket来连接。它的做法介于上面的两种方案之间。
        [WebMethod]
        
public bool GetWaveUpService()
        
{
            
if(WaveUpWebService.M_WaveUpService==null)
            
{
                WaveUpWebService.M_WaveUpService 
= new WaveUpService();
                WaveUpWebService.M_WaveUpService.M_SystemVideoPath 
= WaveUpWebService.M_SystemPath;
                WaveUpWebService.M_WaveUpService.StartWaveUpService();
                
return true;
            }

            
else if(!WaveUpWebService.M_WaveUpService.M_WaveUpServer.M_IsLinstening)
            
{
                WaveUpWebService.M_WaveUpService.Dispose();
                WaveUpWebService.M_WaveUpService 
= new WaveUpService();
                WaveUpWebService.M_WaveUpService.M_SystemVideoPath 
= WaveUpWebService.M_SystemPath;
                WaveUpWebService.M_WaveUpService.StartWaveUpService();
                
return true;
            }

            
else
            
{
                
return true;
            }

        }
这是一个不错的方法。唯一不好的就是内存与线程都在IIS内,容易使IIS挂掉。当然也没什么太大关系,如果真的IIS出现问题,也可以直接再调用WebService方法来恢复。

以上是一些简单的想法,目前项目里对于以上几种方法都实现了,具体的会采用哪一种,到后来再看吧。
我个人认为WindowsService应该是一个不错的选择,不出意外的话,我想我的项目里应该采用这一方案,毕竟它的潜力很大。而且稳定性很好。

posted on 2006-08-18 10:47  Wu.Country@侠缘  阅读(2066)  评论(0编辑  收藏  举报