通常的socket使用,基本上都是调用.Net类库中的Socket类,例如Tcp发送需要经过以下步骤:

  • 获取远程终结点(EndPoint)
  • 建立连接Connect(EndPoint)
  • 发送数据Send

步骤稍显繁杂,并且每一步都有异常要处理,如果再加上同步或异步的选择就更加的复杂,我的目的就是要对Socket一些常用操作如发送、接收进行简化,如发送只有一个方法Send,接收类似,这样只要调用一些简单的方法,订阅一些事件就可以完成复杂的socket调用。

posted @ 2010-01-26 22:11 非空 阅读(65) 评论(0) 编辑
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using Wintellect.Threading.AsyncProgModel;

namespace ExtensionTest
{
    /*
     * 没有异常处理 前两种还没有实现持续接收
     * AsyncEnumerator来自jeffrey rich的Wintellect
     */

    public class NetWork
    {
        private const string ip = "localhost";
        private const int port = 10101;

        private IPEndPoint endPoint;
        private Socket server;

        public NetWork()
        {
            endPoint = new IPEndPoint(Dns.GetHostEntry(ip).AddressList[0], port);

            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            server.Bind(endPoint);
            server.Listen(10);
        }

        public void StartListening()
        {
            server.BeginAccept(AcceptCallback, server);
        }

        public void StartListeningWithIterator()
        {
            AsyncEnumerator asycn = new AsyncEnumerator();
            asycn.Execute(this.StartAsync(asycn));
        }

        private void AcceptCallback(IAsyncResult asyncResult)
        {
            Socket server = asyncResult.AsyncState as Socket;
            if (server != null)
            {
                Socket receiveSocket = server.EndAccept(asyncResult);

                byte[] buffer = new byte[256];

                receiveSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, new State(receiveSocket, buffer));

                //
                this.StartAsync(receiveSocket);
            }
        }

        private void ReceiveCallback(IAsyncResult asyncResult)
        {
            State state = asyncResult.AsyncState as State;

            if (state != null)
            {
                int receBytes = state.Socket.EndReceive(asyncResult);
                if (receBytes > 0)
                    state.Socket.BeginSend(state.Bytes, 0, receBytes, SocketFlags.None, SendCallback, state.Socket);
            }
        }

        private void SendCallback(IAsyncResult asyncResult)
        {
            Socket socket = asyncResult.AsyncState as Socket;
            if (socket != null)
            {
                socket.EndSend(asyncResult);
            }
        }

        private IEnumerator<int> StartAsync(AsyncEnumerator enumerator)
        {
            server.BeginAccept(enumerator.End(), null);

            yield return 1;

            Socket receiveSocket = server.EndAccept(enumerator.DequeueAsyncResult());

            byte[] buffer = new byte[256];

            receiveSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, enumerator.End(), null);

            yield return 1;

            int receLength = receiveSocket.EndReceive(enumerator.DequeueAsyncResult());

            if (receLength > 0)
            {
                receiveSocket.BeginSend(buffer, 0, receLength, SocketFlags.None, enumerator.End(), null);

                yield return 1;

                receiveSocket.EndSend(enumerator.DequeueAsyncResult());
            }
            else
                yield break;
        }

        private void StartAsync(Socket socket)
        {
            AsyncCallback callback = null;

            byte[] buffer = new byte[256];
            callback = receResult =>
                           {
                               int receLength = socket.EndReceive(receResult);

                               if (receLength > 0)
                               {
                                   socket.BeginSend(buffer, 0, receLength, SocketFlags.None, sendResult =>
                                                                                              {
                                                                                                  socket.EndSend(sendResult);
                                                                                                  socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, callback, null);
                                                                                              }, null);
                               }

                           };


            socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, callback, null);
        }

        private class State
        {
            public Socket Socket { get; private set; }
            public byte[] Bytes { get; private set; }

            public State(Socket socket, byte[] bytes)
            {
                this.Socket = socket;
                this.Bytes = bytes;
            }
        }
    }
}
posted @ 2009-07-03 11:06 非空 阅读(355) 评论(0) 编辑
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.ComponentModel;

namespace ExtensionTest
{
    public class Async : IDisposable
    {
        private bool suspend;
        private bool cancel;
        private Stream readStream;
        private Stream writeSteam;
        private AutoResetEvent auto;
        public long TotalLength { get; private set; }
        private AsyncOperation asyncOperation;

        public bool Suspend
        {
            get { return this.suspend; }
            set
            {
                if (this.suspend && !value && !this.auto.SafeWaitHandle.IsClosed)
                    auto.Set();
                this.suspend = value;
            }
        }

        public bool Cancel
        {
            get { return cancel; }
            set { cancel = value; }
        }

        public event EventHandler<ReportEventArgs> ProgressReport;

        public Async()
        {
            asyncOperation = AsyncOperationManager.CreateOperation(null);
            auto = new AutoResetEvent(true);
        }

        /// <summary>
        /// 初始化读写流
        /// </summary>
        /// <param name="fileToRead">用来读取的文件名</param>
        /// <param name="fileToWrite">用来保存的文件名</param>
        private void InitStream(string fileToRead, string fileToWrite)
        {
            if (!File.Exists(fileToRead))
            {
                throw new ArgumentException();
            }

            FileInfo info = new FileInfo(fileToRead);

            //文件大小
            this.TotalLength = info.Length;

            /*
             * 根据文件大小选择选择读取和写入文件的策略
             * 如果大于某个值就构造异步流
             */

            //if (info.Length > 10 * 1024 * 1024)
            //{
            //    readStream = new FileStream(fileToRead, FileMode.Open, FileAccess.Read, FileShare.Read, 1024,
            //                                FileOptions.Asynchronous);
            //}
            //else
            readStream = info.Open(FileMode.Open, FileAccess.Read, FileShare.Read);

            writeSteam = File.Open(fileToWrite, FileMode.Create, FileAccess.Write, FileShare.Write);
        }

        /// <summary>
        /// 使用迭代器开始异步操作
        /// </summary>
        /// <param name="fileToRead">用来读取的文件名</param>
        /// <param name="fileToWrite">用来保存的文件名</param>
        public void StartAsyncOperationWithIterator(string fileToRead, string fileToWrite)
        {
            this.InitStream(fileToRead, fileToWrite);

            ThreadPool.QueueUserWorkItem(arg =>
            {
                byte[] buffer = new byte[1024];
                IEnumerator<int> enumerator = ReadBytes(buffer);
                while (enumerator.MoveNext())
                {
                    if (this.suspend && !auto.SafeWaitHandle.IsClosed)
                        auto.WaitOne();

                    this.asyncOperation.Post(obj => this.OnReportProgress(enumerator.Current), null);

                    /*
                     *如果是Thread.Sleep(0)由于消息发送太快  接收进度报告的窗体也呈假死状态
                     * 而如果是Thread.Sleep(1)则会影响读写速度 惆怅
                     */
                    Thread.Sleep(1);
                }
            });
        }

        private IEnumerator<int> ReadBytes(byte[] buffer)
        {
            try
            {
                int readLength = readStream.Read(buffer, 0, buffer.Length);

                while (readLength > 0)
                {
                    writeSteam.Write(buffer, 0, readLength);

                    yield return readLength;

                    if (this.cancel)
                    {
                        this.Dispose();
                        yield break;
                    }

                    readLength = readStream.Read(buffer, 0, buffer.Length);
                }
            }
            finally
            {
                this.Dispose();
            }

        }

        /// <summary>
        /// 开始异步操作
        /// </summary>
        /// <param name="fileToRead">用来读取的文件名</param>
        /// <param name="fileToWrite">用来保存的文件名</param>
        public void StartAsyncOperation(string fileToRead, string fileToWrite)
        {
            this.StartAsyncOperation(fileToRead, fileToWrite, null);
        }

        /// <summary>
        /// 开始异步操作
        /// </summary>
        /// <param name="fileToRead">用来读取的文件名</param>
        /// <param name="fileToWrite">用来保存的文件名</param>
        /// <param name="completed">完成读写操作后的回调方法</param>
        public void StartAsyncOperation(string fileToRead, string fileToWrite, Action<Exception> completed)
        {
            this.StartAsyncOperation(fileToRead, fileToWrite, null, completed);
        }

        /// <summary>
        /// 开始异步操作
        /// </summary>
        /// <param name="fileToRead">用来读取的文件名</param>
        /// <param name="fileToWrite">用来保存的文件名</param>
        /// <param name="cancelAction">取消时的回调方法</param>
        /// <param name="completed">完成读写操作后的回调方法</param>
        public void StartAsyncOperation(string fileToRead, string fileToWrite, Action cancelAction, Action<Exception> completed)
        {
            this.StartAsyncOperation(fileToRead, fileToWrite, null, cancelAction, completed);
        }

        /// <summary>
        /// 开始异步操作
        /// </summary>
        /// <param name="fileToRead">用来读取的文件名</param>
        /// <param name="fileToWrite">用来保存的文件名</param>
        /// <param name="suspendAction">暂停时的回调方法</param>
        /// <param name="cancelAction">取消时的回调方法</param>
        /// <param name="completed">完成读写操作后的回调方法</param>
        public void StartAsyncOperation(string fileToRead, string fileToWrite, Action<bool> suspendAction, Action cancelAction, Action<Exception> completed)
        {
            this.StartAsyncOperation(fileToRead, fileToWrite, null, suspendAction, cancelAction, completed);
        }

        /// <summary>
        /// 开始异步操作
        /// </summary>
        /// <param name="fileToRead">用来读取的文件名</param>
        /// <param name="fileToWrite">用来保存的文件名</param>
        /// <param name="timeOutAction">超时时调用的方法(只有支持超时的流才会回调)</param>
        /// <param name="suspendAction">暂停时的回调方法</param>
        /// <param name="cancelAction">取消时的回调方法</param>
        /// <param name="completed">完成读写操作后的回调方法</param>
        public void StartAsyncOperation(string fileToRead, string fileToWrite, Action<Operation> timeOutAction, Action<bool> suspendAction, Action cancelAction, Action<Exception> completed)
        {
            this.InitStream(fileToRead, fileToWrite);

            if (readStream == null || writeSteam == null) return;

            byte[] buffer = new byte[1024];

            AsyncCallback callback = null;
            callback = readResult =>
            {
                int readLength = readStream.EndRead(readResult);

                if (readLength > 0)
                {
                    writeSteam.BeginWrite(buffer, 0, readLength, writeResult =>
                    {
                        try
                        {
                            writeSteam.EndWrite(writeResult);

                            //降低cpu使用率
                            Thread.Sleep(0);

                            OnReportProgress(readLength);

                            //暂停
                            if (this.suspend && !this.auto.SafeWaitHandle.IsClosed)
                            {
                                if (suspendAction != null)
                                    suspendAction(true);
                                this.auto.WaitOne();
                            }

                            //取消
                            if (cancel)
                            {
                                this.Dispose();
                                if (cancelAction != null)
                                    asyncOperation.Post(obj => cancelAction(), null);
                                return;
                            }

                            readStream.BeginRead(buffer, 0, buffer.Length, callback, null);
                        }
                        catch (Exception ex)
                        {
                            Dispose();
                            if (completed != null)
                                asyncOperation.Post(obj => completed(ex), null);
                        }
                    }, null);
                }
                else
                {
                    Dispose();
                    if (completed != null)
                        asyncOperation.Post(obj => completed(null), null);
                }
            };

            readStream.BeginRead(buffer, 0, buffer.Length, callback, null);
        }

        private void Dispose()
        {
            readStream.Close();
            readStream.Dispose();
            writeSteam.Close();
            writeSteam.Dispose();
        }

        private void OnReportProgress(int readLength)
        {
            if (this.ProgressReport != null)
            {
                ReportEventArgs args = new ReportEventArgs(readLength, this.TotalLength);

                //发送完成进度报告
                asyncOperation.Post(obj => this.ProgressReport(null, args), null);
            }
        }

        void IDisposable.Dispose()
        {
            auto.Close();
        }
    }

    public enum Operation
    {
        Read,
        Write
    }

    public class ReportEventArgs : EventArgs
    {
        public long CompletedLength { get; private set; }
        public long TotalLength { get; private set; }

        public ReportEventArgs(long completedLength, long totalLength)
        {
            this.CompletedLength = completedLength;
            this.TotalLength = totalLength;
        }
    }
}
posted @ 2009-07-02 22:31 非空 阅读(638) 评论(2) 编辑
posted @ 2009-07-02 16:10 非空 阅读(23) 评论(0) 编辑

关于扩展设计时支持的一些学习和实践心得

posted @ 2009-07-02 16:00 非空 阅读(45) 评论(1) 编辑