原文网址: http://www.cnblogs.com/csdev

Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是:Apache License v2

开源地址是:https://github.com/MarcFletcher/NetworkComms.Net

数据流相关工具

  public static class StreamTools
    {
        #region Static Stream Tools

        /// <summary>
        /// Write the provided sendbuffer to the destination stream in chunks of writeBufferSize. Throws exception if any write takes longer than timeoutPerByteWriteMS.
        /// 把发送缓冲区中的数据写入目标数据流中  每次写入的大小为 writeBufferSize.
        /// 如果写入的时间超过 timeoutPerByteWriteMS  将抛出异常
        /// </summary>
        /// <param name="sendBuffer">发送缓冲区Buffer containing data to write</param>
        /// <param name="inputStart">开始位置  The start position in sendBuffer</param>
        /// <param name="bufferLength">需要写入的字节的大小 The number of bytes to write</param>
        /// <param name="destinationStream">目标数据流 The destination stream</param>
        /// <param name="writeBufferSize">每次写入的缓冲区大小 The size in bytes of each successive write</param>
        /// <param name="timeoutMSPerKBWrite">每KB写入的超时时间 The maximum time to allow for write to complete per KB</param>
        /// <param name="minTimeoutMS">最小超时时间  The minimum time to allow for any sized write</param>
        /// <returns>每KB数据的平均发送时间  The average time in milliseconds per KB written</returns>
        public static double Write(byte[] sendBuffer, int inputStart, int bufferLength, Stream destinationStream, int writeBufferSize, double timeoutMSPerKBWrite, int minTimeoutMS)
        {
            if (sendBuffer == null) throw new ArgumentNullException("sendBuffer");
            if (destinationStream == null) throw new ArgumentNullException("destinationStream");

            using (MemoryStream ms = new MemoryStream(sendBuffer))
            {
                return Write(ms, inputStart, bufferLength, destinationStream, writeBufferSize, timeoutMSPerKBWrite, minTimeoutMS);
            }
        }

        /// <summary>
        /// Write the provided input stream to the destination stream in chunks of writeBufferSize. Throws exception if any write takes longer than timeoutPerByteWriteMS.
        ///把发送缓冲区中的数据写入目标数据流中  每次写入的大小为 writeBufferSize.
        /// 如果写入的时间超过 timeoutPerByteWriteMS  将抛出异常
        /// </summary>
        /// <param name="inputStream">输入的数据流  Input stream containing data to send</param>
        /// <param name="inputStart">输入数据流的开始位置  The start position in inputStream</param>
        /// <param name="inputLength">需写入的数据的大小  The number of bytes to write</param>
        /// <param name="destinationStream">目标数据流 The destination stream</param>
        /// <param name="writeBufferSize">写入数据的缓冲区大小 The size in bytes of each successive write, recommended 8K</param>
        /// <param name="timeoutMSPerKBWrite">每KB数据的超时时间  The maximum time to allow for write to complete per KB</param>
        /// <param name="minTimeoutMS">最小超时时间  The minimum time to wait per write, this takes priority over other values.</param>
        /// <returns>数据的平均发送时间  The average time in milliseconds per KB written</returns>
        public static double Write(Stream inputStream, long inputStart, long inputLength, Stream destinationStream, int writeBufferSize, double timeoutMSPerKBWrite, int minTimeoutMS)
        {
            if (inputStream == null) throw new ArgumentNullException("source");
            if (destinationStream == null) throw new ArgumentNullException("destination");

            //Make sure we start in the right place
            //确保我们开始于正确的位置
            inputStream.Seek(inputStart, SeekOrigin.Begin);
            ;
            long bytesRemaining = inputLength;

            int writeWaitTimeMS = Math.Max(minTimeoutMS, (int)((writeBufferSize / 1024.0) * timeoutMSPerKBWrite));

            System.Diagnostics.Stopwatch timerTotal = new System.Diagnostics.Stopwatch();
            timerTotal.Start();

            byte[] bufferA = new byte[writeBufferSize];
            byte[] bufferB = new byte[writeBufferSize];
            AutoResetEvent readCanStartSignal = new AutoResetEvent(true);
            AutoResetEvent allDataWritten = new AutoResetEvent(false);
            Exception innerException = null;

#if NETFX_CORE
            Action readAction = null; Action<int> writeAction = null;

            Stream input = inputStream;
            Stream output = destinationStream;

            readAction = new Action(async () =>
            {
                try
                {
                while (true)  {

                , (writeBufferSize > bytesRemaining ? (int)bytesRemaining : writeBufferSize));
#else
            AsyncCallback readCompleted = null, writeCompleted = null;

            readCompleted = new AsyncCallback((IAsyncResult ar) =>

            {
                try
                {
                    var streams = ar.AsyncState as Stream[];
                    ];
                    ];

                    // input read asynchronously completed
                    //完成异步读取输入的数据
                    int bytesRead = input.EndRead(ar);
#endif
#if NET2
                    if (!readCanStartSignal.WaitOne(writeWaitTimeMS, false))
#else
                    if (!readCanStartSignal.WaitOne(writeWaitTimeMS))
#endif
                        innerException = new TimeoutException("Write timed out after " + writeWaitTimeMS.ToString() + "ms");

                     || innerException != null)
                    {
                        allDataWritten.Set();
                        return;
                    }

                    var temp = bufferA;
                    bufferA = bufferB;
                    bufferB = temp;

                    // write asynchronously
                    //异步写入
#if NETFX_CORE
                writeAction(bytesRead);
#else
                    output.BeginWrite(bufferB, , bytesRead, writeCompleted, streams);
#endif

                    //start the next read straight away
                    //开始下一阶段的读取
                    totalBytesCompleted += bytesRead;
                    bytesRemaining = inputLength - totalBytesCompleted;

#if NETFX_CORE
                }
#else
                    input.BeginRead(bufferA, , (writeBufferSize > bytesRemaining ? (int)bytesRemaining : writeBufferSize), readCompleted, streams);
#endif
                }
                catch (Exception ex)
                {
                    innerException = ex;
                    allDataWritten.Set();
                    return;
                }
            });

#if NETFX_CORE
            writeAction = new Action<int>(async (bytesRead) =>
            {
                try
                {
                , bytesRead);
#else
            writeCompleted = new AsyncCallback((IAsyncResult ar) =>
            {
                try
                {
                    var streams = ar.AsyncState as Stream[];
                    ];
                    ];

                    try
                    {
                        output.EndWrite(ar);
                    }
                    catch (Exception ex)
                    {
                        innerException = ex;
                    }
#endif
                    readCanStartSignal.Set();
                }
                catch (Exception ex)
                {
                    innerException = ex;
                    allDataWritten.Set();
                    return;
                }
            });

#if NETFX_CORE
            readAction();
#else
            inputStream.BeginRead(bufferA, , (writeBufferSize > bytesRemaining ? (int)bytesRemaining : writeBufferSize), readCompleted, new Stream[] { inputStream, destinationStream });
#endif
            allDataWritten.WaitOne();

            timerTotal.Stop();

            if (innerException != null)
                throw innerException;

            ;
            )
                writeTimePerKBms = (double)timerTotal.ElapsedMilliseconds * 1024.0 / inputLength;

            return writeTimePerKBms;
        }

        /// <summary>
        /// Write the provided input stream to the destination stream
        /// 根据参数 把输入流中的数据写入到输出流中
        /// </summary>
        /// <param name="inputStream">输入流  Input stream containing data to send</param>
        /// <param name="destinationStream">输出流  The destination stream</param>
        /// <returns>每KB数据的平均发送时间 The average time in milliseconds per KB written</returns>
        public static double Write(Stream inputStream, Stream destinationStream)
        {
            , inputStream.Length, destinationStream, , , int.MaxValue);
        }

        /// <summary>
        /// Locker for LogError() which ensures thread safe saves.
        /// 同步锁 用于确保线程安全
        /// </summary>
        static object errorLocker = new object();

        /// <summary>
        /// Appends the provided logString to end of fileName.txt. If the file does not exist it will be created.
        /// 把日志写入到日志文件中
        /// </summary>
        /// <param name="fileName">文件名称 The filename to use. The extension .txt will be appended automatically</param>
        /// <param name="logString">写入的信息  The string to append.</param>
        static void AppendStringToLogFile(string fileName, string logString)
        {
            try
            {
                lock (errorLocker)
                {

#if NETFX_CORE
                    string toWrite = DateTime.Now.Hour.ToString() + "." + DateTime.Now.Minute.ToString() + "." + DateTime.Now.Second.ToString() + "." + DateTime.Now.Millisecond.ToString() + " [" + Environment.CurrentManagedThreadId.ToString() + "] " + logString + Environment.NewLine;

                    Func<Task> writeTask = new Func<Task>(async () =>
                    {
                        StorageFolder folder = ApplicationData.Current.LocalFolder;
                        StorageFile file = await folder.CreateFileAsync(fileName + ".txt", CreationCollisionOption.OpenIfExists);
                        await FileIO.AppendTextAsync(file, toWrite);
                    });

                    writeTask().Wait();
#else
                    using (System.IO.StreamWriter sw = new System.IO.StreamWriter(fileName + ".txt", true))
                        sw.WriteLine(DateTime.Now.Hour.ToString() + "." + DateTime.Now.Minute.ToString() + "." + DateTime.Now.Second.ToString() + "." + DateTime.Now.Millisecond.ToString() + " [" + Thread.CurrentThread.ManagedThreadId.ToString() + "] " + logString);
#endif
                }
            }
            catch (Exception)
            {
                //If an error happens here, such as if the file is locked then we lucked out.
                //错误发生在这里,比如日志文件被锁定
            }
        }

        /// <summary>
        /// Return the MD5 hash of the provided memory stream as a string. Stream position will be equal to the length of stream on
        /// return, this ensures the MD5 is consistent.
        /// 返回参数中内存流的MD5哈希值
        /// 流的位置与返回的流的长度相等
        /// 这样确保md5 是一致的
        /// </summary>
        /// <param name="streamToMD5">数据流  The bytes which will be checksummed</param>
        /// <param name="start">开始位置 The start position in the stream</param>
        /// <param name="length">长度  The length in the stream to MD5</param>
        /// <returns>生成的MD5字符型检验和  The MD5 checksum as a string</returns>
        public static string MD5(Stream streamToMD5, long start, int length)
        {
            if (streamToMD5 == null) throw new ArgumentNullException("streamToMD5", "Provided Stream cannot be null.");

            using (MemoryStream stream = new MemoryStream(length))
            {
                StreamTools.Write(streamToMD5, start, length, stream, , , );
                return MD5(stream);
            }
        }

        /// <summary>
        /// Return the MD5 hash of the provided byte array as a string
        /// 根据参数中的字节数组MD5哈希值
        /// </summary>
        /// <param name="bytesToMd5">字节数组  The bytes which will be checksummed</param>
        /// <returns>返回的Md5值  The MD5 checksum as a string</returns>
        public static string MD5(byte[] bytesToMd5)
        {
            if (bytesToMd5 == null) throw new ArgumentNullException("bytesToMd5", "Provided byte[] cannot be null.");

            , bytesToMd5.Length, false))
                return MD5(stream);
        }

        /// <summary>
        /// Return the MD5 hash of the provided memory stream as a string. Stream position will be equal to the length of stream on
        /// return, this ensures the MD5 is consistent.
        ///  返回参数中内存流的MD5哈希值
        /// 流的位置与返回的流的长度相等
        /// 这样确保md5 是一致的
        /// </summary>
        /// <param name="streamToMD5">数据流  The bytes which will be checksummed</param>
        /// <returns>返回的Md5哈希值  The MD5 checksum as a string</returns>
        public static string MD5(Stream streamToMD5)
        {
            if (streamToMD5 == null) throw new ArgumentNullException("streamToMD5", "Provided Stream cannot be null.");

            string resultStr;

#if NETFX_CORE
            var alg = Windows.Security.Cryptography.Core.HashAlgorithmProvider.OpenAlgorithm(Windows.Security.Cryptography.Core.HashAlgorithmNames.Md5);
            var buffer = (new Windows.Storage.Streams.DataReader(streamToMD5.AsInputStream())).ReadBuffer((uint)streamToMD5.Length);
            var hashedData = alg.HashData(buffer);
            resultStr = Windows.Security.Cryptography.CryptographicBuffer.EncodeToHexString(hashedData).Replace("-", "");
#else
            using (System.Security.Cryptography.HashAlgorithm md5 =
#if WINDOWS_PHONE
                new Tools.MD5Managed())
#else
 System.Security.Cryptography.MD5.Create())
#endif
            {
                //If we don't ensure the position is consistent the MD5 changes
                streamToMD5.Seek(, SeekOrigin.Begin);
                resultStr = BitConverter.ToString(md5.ComputeHash(streamToMD5)).Replace("-", "");
            }
#endif
            return resultStr;
        }
        #endregion

介绍开源的.net通信框架NetworkComms框架 源码分析(十四)StreamTools的更多相关文章

  1. DotNetty网络通信框架学习之源码分析

    DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...

  2. 深入理解分布式调度框架TBSchedule及源码分析

    简介 由于最近工作比较忙,前前后后花了两个月的时间把TBSchedule的源码翻了个底朝天.关于TBSchedule的使用,网上也有很多参考资料,这里不做过多的阐述.本文着重介绍TBSchedule的 ...

  3. 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)

    1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...

  4. 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)

    1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e,  要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...

  5. $Django cbv源码分析 djangorestframework框架之APIView源码分析

    1 CBV的源码分析 #视图 class login (View): pass #路由 url(r'^books/$', views.login.as_view()) #阅读源码: #左侧工程栏--- ...

  6. ④NuPlayer播放框架之Renderer源码分析

    [时间:2016-11] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,渲染器,render] 0 导读 之前我们分析了NuPlayer的实现代码,本文将重点聚 ...

  7. ⑤NuPlayer播放框架之GenericSource源码分析

    [时间:2017-01] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,GenericSource] 0 导读 GenericSource是NuPlayer:: ...

  8. ③NuPlayer播放框架之类NuPlayer源码分析

    [时间:2016-10] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架] 0 引言 差不多一个月了,继续分析AOSP的播放框架的源码.这次我们需要深入分析的是N ...

  9. Laravel开发:Laravel框架门面Facade源码分析

    前言 这篇文章我们开始讲 laravel 框架中的门面 Facade,什么是门面呢?官方文档: Facades(读音:/fəˈsäd/ )为应用程序的服务容器中可用的类提供了一个「静态」接口.Lara ...

  10. Android 应用框架层 SQLite 源码分析

    概述   Android 在应用框架层为开发者提供了 SQLite 相关操作接口,其归属于android.database.sqlite包底下,主要包含SQLiteProgram, SQLiteDat ...

随机推荐

  1. Office 2016 正式发布——新特性预览

    今天微软又发生了一件大事!Windows Office 2016正式发布,这标志着Windows Office 又达到了一个新的里程碑! 全新的Office 发布为Office 365 用户带来了新的 ...

  2. Angularjs学习---ubuntu12.04中karma安装配置中常见的问题总结

    karma启动时出现了很多问题: 1.安装karma前提条件 安装karma首先要安装nodejs,npm然后才可以安装karma.nodejs,npm的安装过程可以参考文章:Angularjs学习- ...

  3. Atitit js中的依赖注入di ioc的实现

    Atitit js中的依赖注入di ioc的实现 全类名(FQCN)为标识符1 混合请求模式1 使用类内  builder  即可..2 Service locator method走ok拦2 Jav ...

  4. AntV 数据可视化解决方案发布

    今天蚂蚁金服发布了一套数据可视化规范AntV. AntV 是一套专业的数据可视化规范,这套规范的目的是为了让可视化的使用者更懂数据可视化.这套规范是蚂蚁金服在可视化建设过程中的理论沉淀,它可以很好得指 ...

  5. 第五章 运输层(UDP和TCP三次握手,四次挥手分析)

    序言   通过这章,可以知道其实三次握手和四次挥手其实真的好简单,通过这章的学习,我相信你也会同样的认为,以后在也不需要听到别人问三次握手的过程而自己一脸懵逼了,觉得人家好屌,其实也就是他懂你不懂,仅 ...

  6. web前端攻击详解

    前端攻击成因 在web网页的脚本中,有些部分的显示内容会依据外界输入值而发生变化,而如果这些声称html的程序中存在问题,就会滋生名为跨站脚本的安全隐患 XSS跨站脚本攻击: 英文全称cross-si ...

  7. 强制SQL Server执行计划使用并行提升在复杂查询语句下的性能

        最近在给一个客户做调优的时候发现一个很有意思的现象,对于一个复杂查询(涉及12个表)建立必要的索引后,语句使用的IO急剧下降,但执行时间不降反升,由原来的8秒升到20秒.     通过观察执行 ...

  8. 【WP 8.1开发】自定义(RAW)通知的使用

    继续前面的话题,还是推送通知.上一篇文章中遗留了RAW通知的推送没有给各位演示,特特地留到现在,不为别的,只为这个RAW通知有点意思,玩起来会比较有意思.官方文档将RAW通知译为“原始通知”,这里还是 ...

  9. 深入理解PHP内核(十)变量及数据类型-类型提示的实现

    原文链接:http://www.orlion.ga/253/ PHP是弱类型语言,向方法传递参数时也并不严格检查数据类型.不过有时候需要判断传递到方法中的参数,为此PHP中提供了一些函数来判断数据的类 ...

  10. kubernetes

    项目主页:http://kubernetes.io/ docker仅能在单机上部署容器,而kubernetes可以统一管理各类容器,形成集群.Kubernetes作为Docker生态圈中重要一员,是G ...