ThreadSafeStream 类(NetworkComms 2.3.1源码了解和学习)

networkComms.net2.3.1开源版本,基于gpl V3协议。因为不能公开3.x版本的源码,所以基于此版本进行学习。3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大。
/*请注意使用以下代码,需遵循GplV3协议*/

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace DPSBase
{
    /// <summary>
    ///    线程安全的数据流  数据流的包装器确保以线程安全的方式访问数据流
    /// </summary>
    public class ThreadSafeStream : IDisposable
    {
        private Stream stream;
        private object streamLocker = new object();

        /// <summary>
        ///
        ///如果设定为True  内部的数据流在数据写入到网络后将会释放
        /// </summary>
        public bool CloseStreamAfterSend { get; private set; }

        /// <summary>
        /// 创建一个线程安全的数据流
        /// </summary>
        /// <param name="stream">The stream to make thread safe</param>
        public ThreadSafeStream(Stream stream)
        {
            this.CloseStreamAfterSend = false;
            this.stream = stream;
        }

         /// <summary>
        /// 创建一个线程安全的数据流
        /// </summary>
        /// <param name="stream">The stream to make thread safe</param>

        public ThreadSafeStream(Stream stream, bool closeStreamAfterSend)
        {
            this.CloseStreamAfterSend = closeStreamAfterSend;
            this.stream = stream;
        }

        /// <summary>
        /// 内部数据流的总长度
        /// </summary>
        public long Length
        {
            get { lock (streamLocker) return stream.Length; }
        }

        /// <summary>
        /// 内部数据流 位置
        /// </summary>
        public long Position
        {
            get { lock (streamLocker) return stream.Position; }
        }

        /// <summary>
        /// 从数据流种返回数据
        /// </summary>
        /// <param name="numberZeroBytesPrefex"> </param>
        /// <returns></returns>
        public byte[] ToArray(int numberZeroBytesPrefex = 0)
        {
            lock (streamLocker)
            {
                stream.Seek(0, SeekOrigin.Begin);
                byte[] returnData = new byte[stream.Length + numberZeroBytesPrefex];
                //把数据读取到数组的指定位置
                stream.Read(returnData, numberZeroBytesPrefex, returnData.Length - numberZeroBytesPrefex);
                return returnData;
            }
        }

        /// <summary>
        /// 从数据流的制定位置返回数据
        /// </summary>

        public byte[] ToArray(long start, long length, int numberZeroBytesPrefex = 0)
        {
            if (length>int.MaxValue)
                throw new ArgumentOutOfRangeException( "length", "Unable to return array whose size is larger than int.MaxValue. Consider requesting multiple smaller arrays.");

            lock (streamLocker)
            {
                if (start + length > stream.Length)
                    throw new ArgumentOutOfRangeException("length", "Provided start and length parameters reference past the end of the available stream.");
                //定位到指定位置
                stream.Seek(start, SeekOrigin.Begin);
                byte[] returnData = new byte[length + numberZeroBytesPrefex];

                //从指定位置读取指定长度的数据 到字节数组的指定位置
                stream.Read(returnData, numberZeroBytesPrefex, returnData.Length - numberZeroBytesPrefex);
                return returnData;
            }
        }

        /// <summary>
        /// 返回MD5的值
        /// </summary>
        /// <returns></returns>
        public string MD5CheckSum()
        {
            lock (streamLocker)
            {
                return MD5Stream(stream);
            }
        }

        public string MD5CheckSum(long start, int length)
        {
            using (MemoryStream partialStream = new MemoryStream(length))
            {
                lock (streamLocker)
                {
                    //从存储数据流的指定开始位置读取指定长度的数据到目标数据流中,并返回其MD5值
                    StreamWriteWithTimeout.Write(stream, start, length, partialStream, 8000, 1000, 500);
                    return MD5Stream(partialStream);
                }
            }
        }

        /// <summary>
         /// 计算md5的值
        /// </summary>
        /// <param name="streamToMD5">The stream to calcualte Md5 for</param>
        /// <returns></returns>
        private static string MD5Stream(Stream streamToMD5)
        {
            streamToMD5.Seek(0, SeekOrigin.Begin);

#if WINDOWS_PHONE
                using(var md5 = new DPSBase.MD5Managed())
                {
#else
            using (var md5 = System.Security.Cryptography.MD5.Create())
            {
#endif
                return BitConverter.ToString(md5.ComputeHash(streamToMD5)).Replace("-", "");
            }
        }

        /// <summary>
        /// 把数据拷贝到数据流的指定位置
        /// </summary>
        /// <param name="data"></param>
        /// <param name="startPosition"></param>
        public void Write(byte[] data, long startPosition)
        {
            if (data == null) throw new ArgumentNullException("data");

            lock (streamLocker)
            {
                //定位到数据流的指定位置
                stream.Seek(startPosition, SeekOrigin.Begin);
                //把缓冲数据拷贝的数据流中
                stream.Write(data, 0, data.Length);
                stream.Flush();
            }
        }

//在英文网站上购买 九折折扣代码: NCDN_PRCLW

//淘宝正版销售 http://shop115882994.taobao.com/ 推广期间 八折优惠

/// <summary>
        /// 把当前类数据流中指定开始位置指定长度的数据拷贝到目标数据流中
        /// </summary>

        public double CopyTo(Stream destinationStream, long startPosition, long length, int writeBufferSize, double timeoutMSPerKBWrite = 1000,  int minTimeoutMS = 500)
        {
            lock (streamLocker)
                return StreamWriteWithTimeout.Write(stream, startPosition, length, destinationStream, writeBufferSize, timeoutMSPerKBWrite, minTimeoutMS);
        }

        /// <summary>
        /// Call Dispose on the internal stream
        ///  释放当前数据流
        /// </summary>
        public void Dispose()
        {
            lock (streamLocker) stream.Dispose();
        }

        /// <summary>
        /// Call Close on the internal stream
        /// </summary>
        public void Close()
        {
            lock (streamLocker) stream.Close();
        }
    }
}
 http://www.cnblogs.com/networkcomms
http://www.networkcoms.cn 编辑
时间: 2024-10-12 13:45:13

ThreadSafeStream 类(NetworkComms 2.3.1源码了解和学习)的相关文章

StreamSendWrapper 类(NetworkComms 2.3.1源码了解和学习)

networkComms.net2.3.1开源版本,基于gpl V3协议.因为不能公开3.x版本的源码,所以基于此版本进行学习.3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大. /*请注意使用以下代码,需遵循GplV3协议*/ using System; using System.Collections.Generic; using System.Text; using System.IO; namespace DPSBase { /// 发送全部或者部分数据流 public cl

ConnectionInfo类(NetworkComms 2.3.1源码了解和学习)

networkComms.net2.3.1开源版本,基于gpl V3协议.因为不能公开3.x版本的源码,所以基于此版本进行学习.3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大. /*请注意使用以下代码,需遵循GplV3协议*/ /// <summary> /// 连接状态枚举类 /// </summary> public enum ConnectionState { /// <summary> /// 未定义 是连接的初始状态. /// </summ

PacketHeaderStringItems枚举类(NetworkComms 2.3.1源码了解和学习)

networkComms.net2.3.1开源版本,基于gpl V3协议.因为不能公开3.x版本的源码,所以基于此版本进行学习.3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大. /*请注意使用以下代码,需遵循GplV3协议*/ ///<summary> /// 字符类型的选项 PacketHeader类中会用到此枚举类型 /// </summary> public enum PacketHeaderStringItems { /// <summary> /

PacketHeaderLongItems枚举类(NetworkComms 2.3.1源码了解和学习)

networkComms.net2.3.1开源版本,基于gpl V3协议.因为不能公开3.x版本的源码,所以基于此版本进行学习.3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大. /*请注意使用以下代码,需遵循GplV3协议*/ /// <summary> /// Long类型的选项 PacketHeader类中会用到此枚举类型 /// </summary> public enum PacketHeaderLongItems { /// <summary>

PacketHeader类(NetworkComms 2.3.1源码了解和学习)

networkComms.net2.3.1开源版本,基于gpl V3协议.因为不能公开3.x版本的源码,所以基于此版本进行学习.3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大. /*请注意使用以下代码,需遵循GplV3协议*/ /// <summary> /// PacketHeader 包含发送,接收,重建数据包的相关信息 /// </summary> [ProtoContract] public sealed class PacketHeader { [Proto

ProtobufSerializer类(NetworkComms 2.3.1源码了解和学习)

networkComms.net2.3.1开源版本,基于gpl V3协议.因为不能公开3.x版本的源码,所以基于此版本进行学习.3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大. /*请注意使用以下代码,需遵循GplV3协议*/ using System; using System.Collections.Generic; using System.Text; using ProtoBuf; using System.IO; using System.Runtime.InteropS

DataSerializerProcessorAttribute类(NetworkComms 2.3.1源码了解和学习)

networkComms.net2.3.1开源版本,基于gpl V3协议.因为不能公开3.x版本的源码,所以基于此版本进行学习.3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大. /*请注意使用以下代码,需遵循GplV3协议*/ //在英文网站上购买 九折折扣代码: NCDN_PRCLW using System; using System.Collections.Generic; using System.Text; namespace DPSBase { /// <summary

SentPacket类(NetworkComms 2.3.1源码了解和学习)

networkComms.net2.3.1开源版本,基于gpl V3协议.因为不能公开3.x版本的源码,所以基于此版本进行学习.3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大. /// 一个包装类用来跟踪发送的数据包 如果检验和失败需要重新发送时可以使用 /// </summary> class SentPacket { public int SendCount { get; private set; } public Packet Packet { get; private s

BinaryFormaterSerializer类(NetworkComms 2.3.1源码了解和学习)

networkComms.net2.3.1开源版本,基于gpl V3协议.因为不能公开3.x版本的源码,所以基于此版本进行学习.3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大. /*请注意使用以下代码,需遵循GplV3协议*/ #if WINDOWS_PHONE #else using System; using System.Collections.Generic; using System.Text; using System.Runtime.Serialization.For