gaoxiang

专注于.NET技术

博客园 首页 新随笔 联系 订阅 管理
 前面我们已经讨论了客户端与服务器通信的一般模式,即Client通过Tcp连接向Server递交请求,Server处理请求后,使用同一Tcp连接将服务结果发送给Client。这一Tcp连接在程序中被抽象成网络流,也就是System.Net.Sockets.NetworkStream类,这个类是非线程安全的。

一.线程安全

如果一个类是线程安全的,表明该类的任何一个实例是线程安全的。也就是说,在多线程的环境中,对任何一个这样的实例的并发访问将被自动同步。由于,同步是由类自己完成的,所以,类的使用者不需要再使用额外的同步机制。

 二.线程安全网络流的意义

按照前面讲述的通信的一般模式,我们也许觉得NetworkStream不需要线程安全机制,因为好像其总是只被单线程访问。简单的情况下确实如此。但是,更常见的需求是,NetworkStream必须支持并发访问。

设想这样一个场景,当一个Client通过Tcp连接上Server后,需要每隔一分钟定时向服务器发送一个Check消息,以表明自己还在线上,这通常是在一个后台线程中完成的。假设某个时刻,主线程正在向Server发送某个功能请求,而同时,后台线程也在发送Check消息。如果网络流是非线程安全的,那么Server端接收到的将是一堆无法解析的数据。有两种方法可以解决这个问题,一是仍然使用System.Net.Sockets.NetworkStream类,只不过由该类的使用者提供同步机制,就像这样,每次调用的NetworkStream方法时先lock

lock(this.networkStream)
{

    
this.networkStream.Write(buffer ,offset ,size ) ;
}

       从客户端开发者的角度来看,这个方法是可以勉强一用的。但是,如果你是一个服务器开发者了,你需要管理的可能是成千上万个NetworkStream,并且,任何时刻都可能有新的NetworkStream建立,也会有NetworkStream被销毁。在这种情况下,仍然使用第一种方法将会死的很难看!
      “所有的软件问题都可以通过引入一个间接层来得到解决”,这是我经常引用的一句话,它可以导出上述问题的第二种解决方案,那就是设计一个线程安全的网络流类SafeNetworkStream,它将自动同步所有的并发访问,它把所有分散的同步代码(比如,lockMonitor等)全部简化并集中在自己的身体里,极大的方便了使用者。 

三.线程安全的网络流的接口与实现

线程安全的网络流的接口ISafeNetworkStream中的方法覆盖了类NetworkStream的几个常用方法,在我们的通信框架中,这个接口中的内容已经够我们使用了。ISafeNetworkStream接口定义如下:

    /// <summary>
    
/// INetworkStreamSafe 线程安全的网络流 。
    
/// 注意:如果调用的异步的begin方法,就一定要调用对应的End方法,否则锁将得不到释放。
    
/// 作者:朱伟 sky.zhuwei@163.com 
    
/// 2005.04.22
    
/// </summary>
    
    
//用于在TCP连接上发送数据,支持同步和异步
    public interface ITcpSender
    {                                                      
        
void Write(byte[] buffer ,int offset ,int size) ;
        IAsyncResult BeginWrite(
byte[] buffer, int offset, int size, AsyncCallback callback, object state );
        
void EndWrite(IAsyncResult asyncResult    );
    }

    
//用于在TCP连接上接收数据,支持同步和异步
    public interface ITcpReciever
    {
        
int Read (byte[] buffer ,int offset ,int size) ;
        IAsyncResult BeginRead(    
byte[] buffer, int offset, int size, AsyncCallback callback, object state );
        
int EndRead(IAsyncResult asyncResult );
    }

    
public interface ISafeNetworkStream :ITcpSender ,ITcpReciever
    {        
        
void Flush();
        
void Close() ;    
    
        NetworkStream NetworkStream{
get ;}
    }    

       接口中各方法的含义与NetworkStream类的方法含义相同。从接口的NetworkStream属性可以推断出,SafeNetworkStream是对NetworkStream的一层薄薄的封装,在这封装的夹层中存在的就是同步机制。
      ISafeNetworkStream接口的实现SafeNetworkStream主要是通过lock来进行同步处理的,其实现代码如下:

SafeNetworkStream
    
    整个实现中,没有什么难的,所以就不多费口舌了。


(注:正在筹备写一本名为《企业级通信框架原理与实现》的书,这此文将是其中的一小片断,请多多建议、指正!)

Feedback

# re: 线程安全的网络流  回复   

2006-02-09 13:46 by li_new
你的代码中锁机制有点问题,不知你有没有进行大量的测试?

# re: 线程安全的网络流  回复   

2006-02-09 17:39 by 黑风
我也感觉如此,StartReadAction ,EndReadAction ,StartWriteAction ,EndWriteAction机制是否安全。

# re: 线程安全的网络流  回复   

2006-02-09 23:44 by 冬冬
我想问一个不太相关的问题,我在作FTP的搜索引擎,但是还没有搞明白怎么和FTPServer比如Serv-U通讯,我在网上找了好久,都没有发现什么很有用的、很系统的资料,不知道楼主有没有这方面的资料,多谢了!

# re: 线程安全的网络流  回复   

2006-02-10 09:06 by zhuwei
@冬冬,我也不是很清楚。请知道的朋友跟贴帮助一下。

# re: 线程安全的网络流  回复   

2006-02-10 09:25 by li_new
@冬冬,你所指的和Serv-U通讯主要指什么?

# re: 线程安全的网络流  回复   

2006-02-10 11:58 by Ariel Y.
@冬冬

当然应该看 FTP(FILE TRANSFER PROTOCOL) (RFC959)

http://www.faqs.org/rfcs/rfc959.html

# re: 线程安全的网络流  回复   

2006-02-10 17:17 by 冬冬
冬冬谢谢搂主和大家的热心帮助了,不过看来……真的要从FTP的传输协议研究了。
其实我的要求很简单,比如怎样解析FTP的List命令给出的信息,得到FTP服务器的内容?至于是不是Serv-U的,倒是无所谓,FTP协议是一样的。

不知道有没有现成的解决方案(封装的类)?
posted on 2006-05-18 13:50  S孤单一吻S  阅读(409)  评论(0)    收藏  举报