获得知识的途径有很多,现在由小编为大家讲解有关语言编程的文章希望对大家有所帮助 |
c语言编程入门前阵子的工作涉及一些网络编程,使用了面向流的方式做传输数据。在代码过程中,遇到一个新需求就是要统计流量。其实最简单的办法就时在读写流的地方增加代码,把功能增加上去就可以。但是我觉得那样对我原理的代码框架影响较大,基于尽量不影响原来的代码的考虑,我想到了Decorator模式。
先把代码贴出来,在做解释吧:
以下为引用的内容: public class EventStream : Stream { public event EventHandler OnBeforeRead; public event EventHandler OnBeforeWrite; private Stream stream; public EventStream(Stream stream) { if (stream == null) throw new ArgumentNullException(“EventStream”); this.stream = stream; } [ ==== Stream members ==== ]#region [ ==== Stream members ==== ] public override bool CanRead { get { return stream.CanRead; } } public override bool CanSeek { get { return stream.CanSeek; } } public override bool CanWrite { get { return stream.CanWrite; } } public override void Flush() { stream.Flush(); } public override long Length { get { return stream.Length; } } public override long Position { get { return stream.Position; } set { stream.Position = value; } } public override int Read(byte[] buffer, int offset, int count) { int readSize = stream.Read(buffer, offset, count); if (OnBeforeRead != null) OnBeforeRead(this, new FStreamDataEventArgs(buffer, offset, readSize)); return readSize; } public override long Seek(long offset, SeekOrigin origin) { return stream.Seek(offset, origin); } public override void SetLength(long value) { stream.SetLength(value); } public override void Write(byte[] buffer, int offset, int count) { if (OnBeforeWrite != null) OnBeforeWrite(this, new FStreamDataEventArgs(buffer, offset, count)); stream.Write(buffer, offset, count); } public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { InternalAsyncState myState = new InternalAsyncState( new FStreamDataEventArgs(buffer, offset, count), state); AsyncCallback myCallback = new AsyncCallback( new InternalCallback(OnBeforeRead, callback).Callback); return new EventStreamAsyncResult( stream.BeginRead(buffer, offset, count, myCallback, myState)); } public override int EndRead(IAsyncResult asyncResult) { EventStreamAsyncResult esar = asyncResult as EventStreamAsyncResult; if (esar != null) return stream.EndRead(esar.InternalAsyncResult); else return stream.EndRead(asyncResult); } public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { InternalAsyncState myState = new InternalAsyncState( new FStreamDataEventArgs(buffer, offset, count), state); AsyncCallback myCallback = new AsyncCallback( new InternalCallback(OnBeforeWrite, callback).Callback); return new EventStreamAsyncResult( stream.BeginWrite(buffer, offset, count, myCallback, myState)); } public override void EndWrite(IAsyncResult asyncResult) { stream.EndWrite(asyncResult); } #endregion private class InternalCallback { private AsyncCallback callback; private EventHandler internalHandler; public InternalCallback(EventHandler internalHandler, AsyncCallback callback) { this.internalHandler = internalHandler; this.callback = callback; } internal void Callback(IAsyncResult asyncResult) { InternalAsyncState myState = asyncResult.AsyncState as InternalAsyncState; if (internalHandler != null && myState != null) internalHandler(this, myState.StreamDataEventArgs); callback(new EventStreamAsyncResult(asyncResult)); } } private class InternalAsyncState { object state; FStreamDataEventArgs streamDataEventArgs; public object State { get { return state; } } public FStreamDataEventArgs StreamDataEventArgs { get { return streamDataEventArgs; } } public InternalAsyncState(FStreamDataEventArgs streamDataEventArgs, object state) { this.streamDataEventArgs = streamDataEventArgs; this.state = state; } } private class EventStreamAsyncResult : IAsyncResult { IAsyncResult ar; public EventStreamAsyncResult(IAsyncResult ar) { if (ar == null) throw new ArgumentNullException(“EventStreamAsyncResult”); this.ar = ar; } IAsyncResult Members#region IAsyncResult Members public object AsyncState { get { InternalAsyncState myState = ar.AsyncState as InternalAsyncState; if (myState != null) return myState.State; else return ar.AsyncState; } } internal IAsyncResult InternalAsyncResult { get { return ar; } } public System.Threading.WaitHandle AsyncWaitHandle { get { return ar.AsyncWaitHandle; } } public bool CompletedSynchronously { get { return ar.CompletedSynchronously; } } public bool IsCompleted { get { return ar.IsCompleted; } } #endregion } } public class FStreamDataEventArgs : EventArgs { private byte[] buffer; private int offset; private int count; public FStreamDataEventArgs(byte[] buffer, int offset, int count) { if(buffer == null) throw new ArgumentNullException(“FStreamDataEventArgs”); if(offset + count>buffer.Length) throw new ArgumentOutOfRangeException(“FStreamDataEventArgs”); this.buffer = buffer; this.offset = offset; this.count = count; } /**//// /// 数据缓存 /// public byte[] Buffer { get { return buffer; } } /**//// /// 数据开始位置 /// public int Offset { get { return offset; } } /**//// /// 数据长度 /// public int Count { get { return count; } } } |
#p#分页标题#e#
“IOBE 编程语言社区排行榜是编程语言流行趋势的一个指标,每月更新,这份排行榜排名基于互联网上有经验的程序员、课程和第三方厂商的数量。排名使用著名的搜索引擎(诸如 Google、MSN、Yahoo!、Wikipedia、YouTube 以及 Baidu 等)进行计算。请注意这个排行榜只是反映某个编程语言的热门程度,并不能说明一门编程语言好不好,或者一门语言所编写的代码数量多少。 教育资源可能会影响结果。例如Python是常用的学校和学习编程途径,成千上万的学生问问题和完成项目。不过根据我的经验来说,Python的工作相比PHP和Ruby来说是罕见的。Java也有类似的情况,因为它在教育、网络、桌面和移动发展上有各种各样的用途,所以它们的排名会相对靠前。
本地开发者的需求仍然很高,尤其是在相关工作的调查中可以看出。RedMonk报告Swift在不到六个月的时间里上升了46个排名达到第22位。然而应用开发是一门年轻的学科。目前有更多的Web和桌面编程职位空缺着。 “
C语言视频教程刚开始以为很简单,事实上写下来还挺多行代码的,Decorator模式嘛,当然先继承stream,把stream本来该做的事情先完成了。这个很简单类里面包含一个内部的stream,stream该有的接口都由它来完成了。接下来就是增加两个事件,分别是OnBeforeRead、OnBeforeWrite。名字里面都有Before,其实我考虑到数据流都会通过这两个事件开放出来,你想做加密什么的都可以,当然也包括我想要的统计数据流量。
接下来就是在读写流的时候触发这两个事件就可以了。看看同步的Read、Write方法,简单的调用就可以了。
关键的地方就在于异步的读写。
我们先看看一般Stream的异步调用代码是怎么样的:
以下为引用的内容: stream.BeginRead(buffer, 0, byte2read, new AsyncCallback(EndReadCallback), state); private void EndReadCallback(IAsyncResult asyncResult) { object state = asyncResult.AsyncState; nReadSize = stream.EndRead(asyncResult); // } |
#p#分页标题#e#
c语言程序设计在不更改这个“client”代码的情况下,要怎么样在stream那边知道这里的确实读了多少数据呢?
显然在调用BeginRead的时候是不知道,那就只能对这个AsyncCallback做手脚了。可以预想到framework内部会在完成了Read的操作之后会调用AsyncCallback委托来通知结果。于是我就传一个我定义好的AsyncCallback委托给BeginRead。当然还要把“client”提供的AsyncCallback给包装起来,在做完我的事情(事件通知)之后,还是要把“client”要我办的事情给也给办了(调用”client”的AsyncCallback委托来通知结果)。
这就在实现了“在客户代码与framework之间插一脚”。
再来看看我是怎么做到事件通知的。首先要把我要的数据给传过去,于是有了InternalAsyncState,这里面要有我触发事件需要的事件参数,还应该要包括用户可能传入的state。具体大家看看InternalAsyncState的实现。
最后多考虑了一点就是,假如“client”代码不是像我写的那样,而是不断的通过检查Stream.BeginRead 方法返回的IAsyncResult的IsCompleted属性来确定是否Read完成的话,那我的代码就有问题了,我返回的IAsyncResult根本就不是原理的IAsyncResult了。EventStreamAsyncResult类就是为这个而写的。
下面是使用的代码:
以下为引用的内容: public void GetResponseStream() { EventStream es = new EventStream(tcpClient.NetStream); es.OnBeforeRead += new EventHandler(EventStream_OnBeforeRead); es.OnBeforeWrite += new EventHandler(EventStream_OnBeforeWrite); return es; } |
#p#分页标题#e#
回头看看代码,其实都在用Decorator模式的思想,把原来的framework中的类都给包装起来,并在完成原来的功能之余另外加了自己的功能。
文笔一般,希望能对你有帮助。
文章很精彩,是否还想了解更多关于视频教程的文章,课课家官网是一个知识的海洋 |