国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

封裝stream,在讀寫stream時提供事件通知

2024-07-21 02:30:10
字體:
來源:轉載
供稿:網友

前陣子的工作涉及一些網絡編程,使用了面向流的方式做傳輸數據。在代碼過程中,遇到一個新需求就是要統計流量。其實最簡單的辦法就時在讀寫流的地方增加代碼,把功能增加上去就可以。但是我覺得那樣對我原理的代碼框架影響較大,基于盡量不影響原來的代碼的考慮,我想到了decorator設計模式。

先把代碼貼出來,在做解釋吧:

   

以下為引用的內容:
 public class eventstream : stream
    {
        public event eventhandler<fstreamdataeventargs> onbeforeread;
        public event eventhandler<fstreamdataeventargs> 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<fstreamdataeventargs> internalhandler;

            public internalcallback(eventhandler<fstreamdataeventargs> 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;
        }

        /**//// <summary>
        /// 數據緩存
        /// </summary>
        public byte[] buffer
        {
          get { return buffer; }
        }

        /**//// <summary>
        /// 數據開始位置
        /// </summary>
        public int offset
        {
          get { return offset; }
        }

        /**//// <summary>
        /// 數據長度
        /// </summary>
        public int count
        {
          get { return count; }
        }
    }

剛開始以為很簡單,事實上寫下來還挺多行代碼的,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);
            //
}

在不更改這個“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<fstreamdataeventargs>(eventstream_onbeforeread);
        es.onbeforewrite += new eventhandler<fstreamdataeventargs>(eventstream_onbeforewrite);
        return es;
}

回頭看看代碼,其實都在用decorator模式的思想,把原來的framework中的類都給包裝起來,并在完成原來的功能之余另外加了自己的功能。

文筆一般,希望能對你有幫助。

注冊會員,創建你的web開發資料庫,
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 高平市| 江津市| 华容县| 阿坝县| 琼结县| 顺平县| 安泽县| 台江县| 神农架林区| 麦盖提县| 松溪县| 利辛县| 东港市| 青铜峡市| 贞丰县| 抚顺县| 城步| 陈巴尔虎旗| 崇明县| 仪征市| 泗洪县| 铁岭市| 吉木萨尔县| 会同县| 思南县| 衡阳市| 灌云县| 特克斯县| 澄迈县| 绥芬河市| 大洼县| 咸丰县| 耿马| 蓬莱市| 西藏| 锡林郭勒盟| 江城| 游戏| 阿勒泰市| 定结县| 博罗县|