西西软件园多重安全检测下载网站、值得信赖的软件下载站!
软件
软件
文章
搜索

首页编程开发C#.NET → C#封装server与client实现异步套接字解决方案

C#封装server与client实现异步套接字解决方案

相关软件相关文章发表评论 来源:BLoodMaster时间:2012/6/1 8:31:12字体大小:A-A+

作者:BLoodMaster点击:93次评论:0次标签: 异步

  • 类型:行业软件大小:1.5M语言:中文 评分:5.0
  • 标签:
立即下载

   最近半年以来都在从事suse10下的C++开发,开发工具也从豪门visual studio10降到了代码查看工具source insight。不过不得不说source insight阅读代码的效率绝对超过visual studio,虽然visual studio也能设置哪些功能,但真心没source insight顺手。不过悲剧的就是写代码的支持比文本好不了多少,调试的话,只能上传到suse10服务器上去然后慢慢的gdb调试了,最头大的就是那个makefile的编写,实在让人累。还是怀念windows下那种豪华的日子。

     废话不多说了,我写这篇文章不是为了诉苦的,只是为了继续写网络这边的。以前写过windows下的C++的网络编程的一些日子,虽然也被喷过不少,不过今天我还是要来写网络编程,只是语言更换为豪华的C#。之所以说C#豪华,相信同时使用C#与C++的人能体会到。

     frame work实在是太强大了,基本我就关注一点点东西就行了,很多类似工具的东西都是可以直接拿过来使用,而且最为关键的是我们在天朝,不用花钱用企业版,小小鄙视下自己,不过我还是会继续支持山寨盗版,谁让我是屌丝呢。

      今天文章中写的是异步,纯粹的异步,当然很多人看来很简单了,而且里面很多东西值得商榷,不过说真的,我真心感谢C#的线程池,不然我还要自己去写个threadpool。而且我没办法保证我写的没问题。

     直接上代码了,不讲思路了,没时间,最近太忙,已经几天没睡好了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace PPT.Comm
{
    /// <summary>
    /// 接收数据流
    /// </summary>
    /// <param name="m_pSocket">异步套接字</param>
    /// <param name="m_pDatagram">接收到的数据流</param>
    public delegate void AsyncDataAcceptedEventHandler(AsyncSocket m_pSocket, byte[] m_pDatagram);

    /// <summary>
    /// 发送完毕
    /// </summary>
    /// <param name="m_pSocket">异步套接字</param>
    /// <param name="m_pIsSuccess">发送结果</param>
    public delegate void AsyncDataSendedEventHandler(AsyncSocket m_pSocket, bool m_pIsSuccess);

    /// <summary>
    /// 接收连接委托
    /// </summary>
    /// <param name="m_pSocket">异步套接字</param>
    public delegate void AsyncSocketAcceptEventHandler(AsyncSocket m_pSocket);

    /// <summary>
    /// 关闭连接委托
    /// </summary>
    /// <param name="m_pSocket">异步套接字</param>
    public delegate void AsyncSocketClosedEventHandler(AsyncSocket m_pSocket);

    /// <summary>
    /// State object for receiving data from remote device.
    /// </summary>
    class StateObject
    {
        // Client socket.
        public Socket workSocket = null;
        // Size of receive buffer.
        public const int BufferSize = 1024 * 256;
        // Receive buffer.
        public byte[] buffer = new byte[BufferSize];
        // Received data string.
        public StringBuilder sb = new StringBuilder();
    }

    /// <summary>
    /// 异步SOCKET
    /// </summary>
    public class AsyncSocket
    {
        #region 私有字段 成员

        private Socket m_socket = null;                                             //socket
        string m_id = "";                                                           //socket唯一标识,GUID

        private readonly bool m_isSerevr;                                           //服务器标志位
        private int m_iBackBag;
        private string m_ipAddress;
        private int m_port;

        private AsyncDataAcceptedEventHandler m_onAsyncDataAcceptedEvent = null;    //接收数据流
        private AsyncDataSendedEventHandler m_onAsyncDataSendedEvent = null;        //发送结束
        private AsyncSocketAcceptEventHandler m_onAsyncSocketAcceptEvent = null;    //接收连接
        private AsyncSocketClosedEventHandler m_onAsyncSocketClosedEvent = null;    //关闭连接
 
        #endregion

        #region 公共属性 成员

        /// <summary>
        /// 获取SOCKET标志位
        /// </summary>
        public string ID 
        {
            get 
            { 
                return m_id;
            } 
        }

        /// <summary>
        /// 设置或获取机器标志位
        /// </summary>
        public string MachineKey 
        { 
            set; 
            get; 
        }

        /// <summary>
        /// 获取、设置连接对象
        /// </summary>
        public Socket LinkObject
        {
            get
            {
                return m_socket;
            }
            set
            {
                m_socket = value;
            }
        }

        /// <summary>
        /// 设置或获取线程退出标识
        /// </summary>
        public bool IsExit { set; get; }

        #endregion

        #region 公共事件 成员

        /// <summary>
        /// 连接关闭事件
        /// </summary>
        public event AsyncSocketClosedEventHandler AsyncSocketClosedEvent
        {
            add
            {
                m_onAsyncSocketClosedEvent += value;
            }
            remove
            {
                m_onAsyncSocketClosedEvent -= value;
            }
        }

        /// <summary>
        /// 连接接收事件
        /// </summary>
        public event AsyncSocketAcceptEventHandler AsyncSocketAcceptEvent
        {
            add
            {
                m_onAsyncSocketAcceptEvent += value;
            }
            remove
            {
                m_onAsyncSocketAcceptEvent -= value;
            }
        }

        /// <summary>
        /// 数据接收完成事件
        /// </summary>
        public event AsyncDataAcceptedEventHandler AsyncDataAcceptedEvent
        {
            add
            {
                this.m_onAsyncDataAcceptedEvent += value;
            }
            remove
            {
                this.m_onAsyncDataAcceptedEvent -= value;
            }
        }

        /// <summary>
        /// 数据发送完成事件
        /// </summary>
        public event AsyncDataSendedEventHandler AsyncDataSendedEvent
        {
            add
            {
                m_onAsyncDataSendedEvent += value;
            }
            remove
            {
                m_onAsyncDataSendedEvent -= value;
            }
        }

        #endregion

        #region 构造函数 成员

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="m_pHostAddrss">主机地址,可为机器名或者IP</param>
        /// <param name="m_pHostPort">主机端口</param>
        /// <param name="m_pIsAsServer">是否作为服务器,默认为false</param>
        /// <param name="m_pICount">支持多少个客户端</param>
        public AsyncSocket(string m_pHostAddrss, int m_pHostPort, bool m_pIsAsServer = false, int m_pIBackBag = 10)
        {
            m_isSerevr = m_pIsAsServer;
            m_iBackBag = m_pIBackBag;
            m_ipAddress = m_pHostAddrss;
            m_port = m_pHostPort;
            m_id = Guid.NewGuid().ToString();
        }

        /// <summary>
        /// 构造函数,用于服务器构造与客户端的异步socket
        /// </summary>
        /// <param name="LinkObject">客户端socket</param>
        private AsyncSocket(Socket linkObject)
        {
            m_socket = linkObject;
            m_id = Guid.NewGuid().ToString();
        }

        #endregion

        #region 公共方法

        /// <summary>
        /// 打开通道
        /// </summary>
        public void AsyncOpen()
        {
            if (m_isSerevr)
            {
                IPAddress ip = Dns.GetHostAddresses(m_ipAddress)[0];
                IPEndPoint ipe = new IPEndPoint(ip, m_port);
                m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                m_socket.Bind(ipe);
                m_socket.Listen(m_iBackBag);
                m_socket.BeginAccept(new AsyncCallback(AcceptCallBack), null);//异步
            }
            else
            {
                IPAddress ip = Dns.GetHostAddresses(m_ipAddress)[0];
                IPEndPoint ipe = new IPEndPoint(ip, m_port);
                m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                m_socket.Connect(ipe);
            }
        }

        /// <summary>
        /// 发送二进制数据
        /// </summary>
        /// <param name="SendData"></param>
        public void AsyncSend(byte[] SendData)
        {
            m_socket.BeginSend(SendData, 0, SendData.Length, 0, new AsyncCallback(SendCallBack), m_socket);
        }

        /// <summary>
        /// 关闭通道
        /// </summary>
        public void AsyncClose()
        {
            if (!m_isSerevr)
            {
                m_socket.Shutdown(SocketShutdown.Both);//关闭接收发送流
                m_socket.BeginDisconnect(false, CloseCallBack, m_socket);//开始尝试断开
            }
            else 
            {
                m_socket.Shutdown(SocketShutdown.Both);//关闭接收发送流
                Thread.Sleep(200);//等待现有任务处理完成
                m_socket.Dispose();//释放所有本地资源
            }
        }

        /// <summary>
        /// 开始接受数据,连接建立之后,调用此方法
        /// </summary>
        public void BeginAcceptData()
        {
            //开始接收数据
            StateObject state = new StateObject();
            state.workSocket = m_socket;
            m_socket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
        }

        #endregion

        #region 私有方法 成员

        #endregion

        #region 回调函数 成员

        /// <summary>
        /// 接受客户端连接处理
        /// </summary>
        /// <param name="ar"></param>
        private void AcceptCallBack(IAsyncResult ar)
        {
            Socket handler = m_socket.EndAccept(ar);
            AsyncSocket NewSocket = new AsyncSocket(handler);

            //激发事件,异步触发
            if (m_onAsyncSocketAcceptEvent != null)
                foreach (AsyncSocketAcceptEventHandler item in m_onAsyncSocketAcceptEvent.GetInvocationList())
                    item.BeginInvoke(NewSocket, null, null);

            //继续投递监听请求
            m_socket.BeginAccept(new AsyncCallback(AcceptCallBack), null);
        }

        /// <summary>
        /// 接受字节流处理
        /// </summary>
        /// <param name="ar"></param>
        private void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                StateObject state = ar.AsyncState as StateObject;
                //读取数据
                int bytesRead = m_socket.EndReceive(ar);
                if (bytesRead > 0)
                {
                    byte[] _Readbyte = new byte[bytesRead];
                    Array.Copy(state.buffer, 0, _Readbyte, 0, bytesRead);
                    //接收完成,激发事件
                    if (m_onAsyncDataAcceptedEvent != null)
                        foreach (AsyncDataAcceptedEventHandler item in m_onAsyncDataAcceptedEvent.GetInvocationList())
                            item.BeginInvoke(this, _Readbyte, null, null);

                    state = new StateObject();//继续投递接收委托
                    state.workSocket = m_socket;
                    m_socket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
                }
            }
            catch (SocketException)
            {
                if (m_onAsyncSocketClosedEvent != null)
                    foreach (AsyncSocketClosedEventHandler item in m_onAsyncSocketClosedEvent.GetInvocationList())
                        item.BeginInvoke(this, null, null);
            }
        }

        /// <summary>
        /// 发送结束处理
        /// </summary>
        /// <param name="ar"></param>
        private void SendCallBack(IAsyncResult ar)
        {
            try
            {
                m_socket.EndSend(ar);
                if (m_onAsyncDataSendedEvent != null)
                    foreach (AsyncDataSendedEventHandler item in m_onAsyncDataSendedEvent.GetInvocationList())
                        item.BeginInvoke(this, true, null, null);
            }
            catch (SocketException)
            {
                if (m_onAsyncDataSendedEvent != null)
                    foreach (AsyncDataSendedEventHandler item in m_onAsyncDataSendedEvent.GetInvocationList())
                        item.BeginInvoke(this, false, null, null);

                if (m_onAsyncSocketClosedEvent != null)
                    foreach (AsyncSocketClosedEventHandler item in m_onAsyncSocketClosedEvent.GetInvocationList())
                        item.BeginInvoke(this, null, null);
            }
        }

        /// <summary>
        /// 关闭后处理
        /// </summary>
        /// <param name="ar"></param>
        private void CloseCallBack(IAsyncResult ar)
        {
            try
            {
                m_socket.EndDisconnect(ar);
                m_socket.Dispose();
                if (m_onAsyncDataSendedEvent != null)
                    foreach (AsyncSocketClosedEventHandler item in m_onAsyncSocketClosedEvent.GetInvocationList())
                        item.BeginInvoke(this, null, null);
            }
            catch (SocketException)
            {
                if (m_onAsyncSocketClosedEvent != null)
                    foreach (AsyncSocketClosedEventHandler item in m_onAsyncSocketClosedEvent.GetInvocationList())
                        item.BeginInvoke(this, null, null);
            }  
        }

        #endregion
    }
}

   代码注释还是蛮详细的,相信你看了也没什么不懂的地方。唯一让我不爽的是我异步事件不得不

                foreach (AsyncSocketAcceptEventHandler item in m_onAsyncSocketAcceptEvent.GetInvocationList())

                    item.BeginInvoke(NewSocket, null, null); 

这样的写法,很蛋疼。也试验了

Action asyncAction = () => m_onAsyncSocketAcceptEvent ();

asyncAction.BeginInvoke( null , null); 

 但郁闷的发现其实action虽然异步了,但那些事件还是顺序触发的,根本不是并发触发。无奈还是写那个蛋疼的foreach语句。顺便提到一句那个foreach中类型写全了,别用var,因为var会自动推断为Delegate。当然你自己再转换下也行,如果你喜欢的话。

我把代码贴出来的目的是找bug,还望各位大神多多指出其中问题。各种都可以,包括性能方面的。(我现在最怀疑的就是这里面到处异步,用线程池的资源会不会出现性能问题,毕竟线程有时候就是坑爹的) 

    相关评论

    阅读本文后您有什么感想? 已有人给出评价!

    • 8 喜欢喜欢
    • 3 顶
    • 1 难过难过
    • 5 囧
    • 3 围观围观
    • 2 无聊无聊

    热门评论

    最新评论

    发表评论 查看所有评论(0)

    昵称:
    表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲
    字数: 0/500 (您的评论需要经过审核才能显示)