介绍开源的.net通信框架NetworkComms框架 源码分析(十四)StreamTools
原文网址: 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的更多相关文章
- DotNetty网络通信框架学习之源码分析
DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...
- 深入理解分布式调度框架TBSchedule及源码分析
简介 由于最近工作比较忙,前前后后花了两个月的时间把TBSchedule的源码翻了个底朝天.关于TBSchedule的使用,网上也有很多参考资料,这里不做过多的阐述.本文着重介绍TBSchedule的 ...
- 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)
1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...
- 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)
1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e, 要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...
- $Django cbv源码分析 djangorestframework框架之APIView源码分析
1 CBV的源码分析 #视图 class login (View): pass #路由 url(r'^books/$', views.login.as_view()) #阅读源码: #左侧工程栏--- ...
- ④NuPlayer播放框架之Renderer源码分析
[时间:2016-11] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,渲染器,render] 0 导读 之前我们分析了NuPlayer的实现代码,本文将重点聚 ...
- ⑤NuPlayer播放框架之GenericSource源码分析
[时间:2017-01] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,GenericSource] 0 导读 GenericSource是NuPlayer:: ...
- ③NuPlayer播放框架之类NuPlayer源码分析
[时间:2016-10] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架] 0 引言 差不多一个月了,继续分析AOSP的播放框架的源码.这次我们需要深入分析的是N ...
- Laravel开发:Laravel框架门面Facade源码分析
前言 这篇文章我们开始讲 laravel 框架中的门面 Facade,什么是门面呢?官方文档: Facades(读音:/fəˈsäd/ )为应用程序的服务容器中可用的类提供了一个「静态」接口.Lara ...
- Android 应用框架层 SQLite 源码分析
概述 Android 在应用框架层为开发者提供了 SQLite 相关操作接口,其归属于android.database.sqlite包底下,主要包含SQLiteProgram, SQLiteDat ...
随机推荐
- [异常解决] Keil安装好nRF51822开发环境,运行DEMO报错:Error:“GPIOTE_CONFIG_NUM_OF_LOW_POWER_ENVENTS” is undefined
1.问题描述 when compiling "ble_app_proximity" exampled by Nordic, it indicates errors: "D ...
- 我所理解的OOP——UML六种关系
最近由于经常给公司的小伙伴儿们讲一些OOP的基本东西,每次草纸都被我弄的很尴尬,画来画去自己都乱了,有时候也会尝试使用UML表示类之间的关系,但UML从毕业后就再也没接触过了,经常会被小伙伴儿们指出继 ...
- Atitit 作用域的理解attilax总结
Atitit 作用域的理解attilax总结 1.1. 作用域是指对某一变量和方法具有访问权限的代码空间, 1 1.2. 作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突.1 1.3 ...
- Android Studio导入System Library步骤
转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6242170.html 请尊重知识产权!!! 同步更新到CSDN:http://blog.csdn.net ...
- SQL SERVER 2005/2008 中关于架构的理解(一)
SQL SERVER 2005/2008 中关于架构的理解(一) 在一次的实际工作中碰到以下情况,在 SQL SERVER 2008中,新建了一个新用户去访问几张由其他用户创建的表,但是无法进行查询, ...
- IBM appscan 9.0破解版分享
简介:IBM AppScan该产品是一个领先的 Web 应用安全测试工具,曾以 Watchfire AppScan 的名称享誉业界.Rational AppScan 可自动化 Web 应用的安全漏洞评 ...
- 【原创】高性能网络编程(二):上一个10年,著名的C10K并发连接问题
1.前言 对于高性能即时通讯技术(或者说互联网编程)比较关注的开发者,对C10K问题(即单机1万个并发连接问题)应该都有所了解."C10K"概念最早由Dan Kegel发布于其个人 ...
- java 中获取2个时间段中所包含的周数(股票的周数->从周六到周五)
Calendar 类中是以周日为开始的第一天的,所以Calendar.DAY_OF_WEEK为1的时候是周日. 在股票中有日K 周K和月K的数据. 在此之中的周K是指交易日中一周的数据,周六到周五为 ...
- Python之文件读写
本节内容: I/O操作概述 文件读写实现原理与操作步骤 文件打开模式 Python文件操作步骤示例 Python文件读取相关方法 文件读写与字符编码 一.I/O操作概述 I/O在计算机中是指Input ...
- Sql Server 的本地时间和UTC时间
一,本地时间和UTC时间 本地时间 世界的每个地区都有自己的本地时间,整个地球分为二十四时区,每个时区都有自己的本地时间. UTC时间 在国际无线电通信中,为统一而普遍使用一个标准时间,称为通用协调时 ...