介绍开源的.net通信框架NetworkComms框架 源码分析(十三)ThreadSafeStream
原文网址: http://www.cnblogs.com/csdev
Networkcomms 是一款C# 语言编写的TCP/UDP通信框架 作者是英国人 以前是收费的 目前作者已经开源 许可是:Apache License v2
开源地址是:https://github.com/MarcFletcher/NetworkComms.Net
线程安全的数据流
/// <summary>
/// A wrapper around a stream to ensure it can be accessed in a thread safe way. The .net implementation of Stream.Synchronized is not suitable on its own.
/// 线程安全的数据流 .net实现的Stream.Synchronized 不适合其本身
/// </summary>
public class ThreadSafeStream : Stream, IDisposable
{
private Stream _innerStream;
private object streamLocker = new object();
/// <summary>
/// If true the internal stream will be disposed once the data has been written to the network
/// 如果设置为True 当数据写入到网络后 内部的数据流将会释放
/// </summary>
public bool DiposeInnerStreamOnDispose { get; set; }
/// <summary>
/// Create a thread safe stream. Once any actions are complete the stream must be correctly disposed by the user.
/// 创建一个新的线程安全数据流 一旦操作完成数据流必须正确的释放
/// </summary>
/// <param name="stream">The stream to make thread safe</param>
public ThreadSafeStream(Stream stream)
{
this.DiposeInnerStreamOnDispose = false;
this._innerStream = stream;
}
/// <summary>
/// Create a thread safe stream.
/// 创建一个新的线程安全数据流
/// </summary>
/// <param name="stream">数据流 The stream to make thread safe.</param>
/// <param name="closeStreamAfterSend">发送完成后内部数据流是否释放 If true the provided stream will be disposed once data has been written to the network. If false the stream must be disposed of correctly by the user</param>
public ThreadSafeStream(Stream stream, bool closeStreamAfterSend)
{
this.DiposeInnerStreamOnDispose = closeStreamAfterSend;
this._innerStream = stream;
}
/// <summary>
/// The total length of the internal stream
/// 内部数据流的长度
/// </summary>
public override long Length
{
get { lock (streamLocker) return _innerStream.Length; }
}
/// <inheritdoc />
public override void SetLength(long value)
{
lock (streamLocker) _innerStream.SetLength(value);
}
/// <summary>
/// The current position of the internal stream
/// 内部数据流的当前位置
/// </summary>
public override long Position
{
get { lock (streamLocker) return _innerStream.Position; }
set { lock (streamLocker) _innerStream.Position = value; }
}
/// <inheritdoc />
public override long Seek(long offset, SeekOrigin origin)
{
lock (streamLocker) return _innerStream.Seek(offset, origin);
}
/// <summary>
/// Returns data from entire Stream
/// 从数据流中返回所有数据
/// </summary>
/// <param name="numberZeroBytesPrefex">是否存在0前缀 If non zero will append N 0 value bytes to the start of the returned array</param>
/// <returns></returns>
)
{
lock (streamLocker)
{
_innerStream.Seek(, SeekOrigin.Begin);
byte[] returnData = new byte[_innerStream.Length + numberZeroBytesPrefex];
_innerStream.Read(returnData, numberZeroBytesPrefex, returnData.Length - numberZeroBytesPrefex);
return returnData;
}
}
/// <summary>
/// Returns data from the specified portion of Stream
/// 从数据流的指定位置返回数据
/// </summary>
/// <param name="start">开始位置 The start position of the desired bytes</param>
/// <param name="length">长度 The total number of desired bytes, not including the zero byte prefix and append parameters</param>
/// <param name="numberZeroBytesPrefix">0前缀 If non zero will append N 0 value bytes to the start of the returned array</param>
/// <param name="numberZeroBytesAppend">0后缀 If non zero will append N 0 value bytes to the end of the returned array</param>
/// <returns></returns>
, )
{
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 > _innerStream.Length)
throw new ArgumentOutOfRangeException("length", "Provided start and length parameters reference past the end of the available stream.");
_innerStream.Seek(start, SeekOrigin.Begin);
byte[] returnData = new byte[length + numberZeroBytesPrefix + numberZeroBytesAppend];
_innerStream.Read(returnData, numberZeroBytesPrefix, (int)length);
return returnData;
}
}
/// <summary>
/// Return the MD5 hash of the current <see cref="ThreadSafeStream"/> as a string
/// 返回当前“线程安全数据流”的MD5哈希值
/// </summary>
/// <returns></returns>
public string MD5()
{
lock (streamLocker)
return StreamTools.MD5(_innerStream);
}
/// <summary>
/// Return the MD5 hash of part of the current <see cref="ThreadSafeStream"/> as a string
/// 返回当前“线程安全数据流”指定部分的MD5哈希值
/// </summary>
/// <param name="start">开始位置 The start position in the stream</param>
/// <param name="length">长度 The length of stream to MD5</param>
/// <returns></returns>
public string MD5(long start, int length)
{
using (MemoryStream partialStream = new MemoryStream(length))
{
lock (streamLocker)
{
StreamTools.Write(_innerStream, start, length, partialStream, , , );
return StreamTools.MD5(partialStream);
}
}
}
/// <summary>
/// Writes the provided buffer to the internal stream starting at the provided position within the internal stream
/// 把 字节数组 从内部数据流指定的位置开始写入
/// </summary>
/// <param name="buffer"></param>
/// <param name="startPosition"></param>
public void Write(byte[] buffer, long startPosition)
{
if (buffer == null) throw new ArgumentNullException("data");
lock (streamLocker)
{
_innerStream.Seek(startPosition, SeekOrigin.Begin);
_innerStream.Write(buffer, , buffer.Length);
_innerStream.Flush();
}
}
/// <inheritdoc />
public override void Write(byte[] buffer, int offset, int count)
{
if (buffer == null) throw new ArgumentNullException("buffer");
lock (streamLocker) _innerStream.Write(buffer, offset, count);
}
/// <summary>
/// Copies data specified by start and length properties from internal stream to the provided stream.
/// 根据参数 从指定的开始位置复制指定长度的内部数据流到目标数据流中
/// </summary>
/// <param name="destinationStream">目标数据流 The destination stream to write to</param>
/// <param name="startPosition"></param>
/// <param name="length"></param>
/// <param name="writeBufferSize">写入的缓冲区大小 The buffer size to use for copying stream contents</param>
/// <param name="minTimeoutMS">超时最小时间 The minimum time allowed for any sized copy</param>
/// <param name="timeoutMSPerKBWrite">每KB数据发送的超时时间 The timouts in milliseconds per KB to write</param>
/// <returns>每KB数据发送的平均时间 The average time in milliseconds per byte written</returns>
, )
{
lock (streamLocker)
return StreamTools.Write(_innerStream, startPosition, length, destinationStream, writeBufferSize, timeoutMSPerKBWrite, minTimeoutMS);
}
/// <summary>
/// Attempts to return the buffer associated with the internal stream. In certain circumstances this is more efficient
/// than copying the stream contents into a new buffer using ToArray. If the internal stream is not a memory stream
/// will throw InvalidCastException. If access to the buffer is not allowed will throw an UnauthorizedAccessException.
/// 尝试返回内部流相关的缓冲区。
/// 在某些情况下,这比使用ToArray复制内容到一个新的缓冲区中更高效
/// 如果内部数据流不是内存流 将会抛出异常
/// 如果缓冲区不可访问 ,也会抛出异常
/// </summary>
/// <returns></returns>
public byte[] GetBuffer()
{
#if NETFX_CORE
throw new NotImplementedException("This method has not been implemented for Win RT");
#else
MemoryStream _innerMemoryStream = _innerStream as MemoryStream;
if (_innerMemoryStream != null)
return _innerMemoryStream.GetBuffer();
else
throw new InvalidCastException("Unable to return stream buffer as inner stream is not a MemoryStream.");
#endif
}
/// <inheritdoc />
public override int Read(byte[] buffer, int offset, int count)
{
lock (streamLocker) return _innerStream.Read(buffer, offset, count);
}
/// <summary>
/// Disposes the internal stream if <see cref="DiposeInnerStreamOnDispose"/> is true.
/// Use Close() to close the inner stream regardless of <see cref="DiposeInnerStreamOnDispose"/>.
/// 如果 DiposeInnerStreamOnDispose属性设置为TRUE,释放内部数据流
/// </summary>
public new void Dispose()
{
if (DiposeInnerStreamOnDispose)
{
lock (streamLocker) _innerStream.Dispose();
}
}
/// <summary>
/// Disposes the internal stream. If <see cref="DiposeInnerStreamOnDispose"/> is false, forceDispose
/// must be true to dispose of the internal stream.
/// 如果 DiposeInnerStreamOnDispose属性设置为False ,强制释放设定为True,来释放内部数据流
/// </summary>
/// <param name="forceDispose">If true the internal stream will be disposed regardless of <see cref="DiposeInnerStreamOnDispose"/> value.</param>
public new void Dispose(bool forceDispose)
{
if (DiposeInnerStreamOnDispose || forceDispose)
{
lock (streamLocker) _innerStream.Dispose();
}
}
/// <inheritdoc />
public override bool CanRead
{
get { lock (streamLocker) return _innerStream.CanRead; }
}
/// <inheritdoc />
public override bool CanSeek
{
get { lock (streamLocker) return _innerStream.CanSeek; }
}
/// <inheritdoc />
public override bool CanWrite
{
get { lock (streamLocker) return _innerStream.CanWrite; }
}
/// <inheritdoc />
public override void Flush()
{
lock (streamLocker) _innerStream.Flush();
}
}
介绍开源的.net通信框架NetworkComms框架 源码分析(十三)ThreadSafeStream的更多相关文章
- 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 ...
随机推荐
- Spring将多个配置文件引入一个配置文件中
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- CenOS 7 安装mysql
1:安装YUM源 2:利用file zilla 将mysql文件拖放到 /var/opt 目录下 3:在centos当中,已经将mysql的文件放到了 /var/opt 我们只需要安装就可以 安装 ...
- 07 Linux su和sudo命令的区别
一. 使用 su 命令临时切换用户身份 1.su 的适用条件和威力 su命令就是切换用户的工具,怎么理解呢?比如我们以普通用户beinan登录的,但要添加用户任务,执行useradd ,beinan用 ...
- POJ2411
题目大意:一个宽w高为h的棋盘,现在要用1*2的多米诺骨牌不重叠地覆盖整个棋盘,问有多少种方案. h<11,w<11 分析:1.h*w若为奇数,则无解. 2.按行处理.处理第i行时,保证前 ...
- IOS中图片拉伸技巧与方法总结(转载)
以下内容转载自:http://my.oschina.net/u/2340880/blog/403996 IOS中图片拉伸技巧与方法总结 一.了解几个图像拉伸的函数和方法 1.直接拉伸法 简单暴力,却是 ...
- 黄聪:Wordpress二级域名共享用户cookie出现错误解决方案及WP的Cookie机制
在若干年以前,我刚开始折腾Wordpress没多久的时候,就自己摸索过 多个Wordpress网站共享一份数据表的实现方法 .这种看起来好像很高大上的类SSO功能,能够给用户在多个网站之间提供快速.无 ...
- 在 github 上获取源码
比如访问: https://github.com/alifellod/NWebGather 可以找到下面的源码获取方式. 在github开源项目的页面上可以找到上图的三个获取源码方式. 使用git的网 ...
- [MongoDB] 高可用架构方案
一.缘由: 众所周知,Mongodb是在高速发展期,一些特性架构难免会发生变化.这里就总结下,我目前所知道的Mongodb 的高可用架构都有哪些.目前Mongodb版本3.2. 二.结构介绍: 1.R ...
- [家里蹲大学数学杂志]第269期韩青编《A Basic Course in Partial Differential Equations》 前五章习题解答
1.Introduction 2.First-order Differential Equations Exercise2.1. Find solutons of the following inti ...
- 利用Manacher算法寻找字符串中的最长回文序列(palindrome)
寻找字符串中的最长回文序列和所有回文序列(正向和反向一样的序列,如aba,abba等)算是挺早以前提出的算法问题了,最近再刷Leetcode算法题的时候遇到了一个(题目),所以就顺便写下. 如果用正反 ...