编写TCP异步通信组件之AsyncTCPServer

最近写了两个异步socket组件:
在SocketLibrary里面有两个TCP异步通信组件,分别是:AsyncTCPServer, AsyncTCPClient,同时里面包含测试程序

经过测试,客户端连接达到10000个以上的情况下,通信正常。
如果有什么问题或建议请给我发邮件:michelsn#163.com (请把 # 用 @ 替换掉) 

 

/*
 *
 *      作者:俞伟
 *      时间:2007-11-29
 *      作用:声明AsyncTCPServer类,TCP异步通信服务端
 *      邮件:michelsn@163.com
 *
 * */


using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace SocketLibrary {
    public partial class AsyncTCPServer : Component {

        #region 构造函数

        public AsyncTCPServer() {
            InitializeComponent();
        }

        public AsyncTCPServer(IContainer container) {
            container.Add(this);

            InitializeComponent();
        }

        #endregion

        #region 私有变量

        private Socket mSocket = null;
        private string keyID = "";
        private bool active = false;
        private ArrayList clientSocketList = new ArrayList();
        private bool IsExit = false;

        #endregion

        #region 变量属性

        /// <summary>
        /// Socket标志
        /// </summary>
        public string KeyID {
            get {
                return keyID;
            }
        }

        /// <summary>
        /// Socket通信状态
        /// </summary>
        public bool Active {
            get {
                return active;
            }
        }

        /// <summary>
        /// 消息的终止判断符
        /// </summary>
        public static string EndChar {
            get {
                return new string((char)0, 1);
            }
        }


        /// <summary>
        /// 客户端管理队列
        /// </summary>
        public ArrayList ClientSocketList {
            get {
                return clientSocketList;
            }
        }

        #endregion

        #region 代理委托

        /// <summary>
        /// Socket异常错误事件
        /// </summary>
        /// <param name="aKeyID">异常错误所有者的标志值</param>
        /// <param name="aErrorMessage">异常错误信息</param>
        public delegate void SocketErrorHandler(string aKeyID, string aErrorMessage);

        /// <summary>
        /// 停止Socket通信之前
        /// </summary>
        /// <param name="aAsyncTCPServer">AsyncTCPServer对象</param>
        public delegate void BeforeStopHandler(AsyncTCPServer aAsyncTCPServer);

        /// <summary>
        /// 停止Socket通信之后
        /// </summary>
        /// <param name="aAsyncTCPServer">AsyncTCPServer</param>
        public delegate void AfterStopHandler(AsyncTCPServer aAsyncTCPServer);

        /// <summary>
        /// 接受新的Socket通信连接请求
        /// </summary>
        /// <param name="aNewSocket">新接受的Socket通信连接对象</param>
        public delegate void AcceptSocketHandler(Socket aNewSocket);

        /// <summary>
        /// 接收二进制数据
        /// </summary>
        /// <param name="aKeyID">接收到数据的Socket标志</param>
        /// <param name="aData">接收到的数据</param>
        /// <param name="aSocket">接收到数据的Socket</param>
        public delegate void BinaryDataAvailableHandler(string aKeyID, byte[] aData, SocketObject aSocketObject);

        /// <summary>
        /// 接收字符串数据
        /// </summary>
        /// <param name="aKeyID">接收到数据的Socket标志</param>
        /// <param name="aData">接收到的数据</param>
        /// <param name="aSocket">接收到数据的Socket</param>
        public delegate void StringDataAvailableHandler(string aKeyID, string aData, SocketObject aSocketObject);

        /// <summary>
        /// 客户端断开连接
        /// </summary>
        /// <param name="aKeyID">客户端对应的Socket标志</param>
        public delegate void CloseClientSocketHandler(string aKeyID);

        #endregion

        #region 事件声明

        public event SocketErrorHandler OnSocketError;
        public event BeforeStopHandler OnBeforeStop;
        public event AfterStopHandler OnAfterStop;
        public event AcceptSocketHandler OnAcceptClientSocket;
        public event BinaryDataAvailableHandler OnBinaryDataAvailable;
        public event StringDataAvailableHandler OnStringDataAvailable;
        public event CloseClientSocketHandler OnCloseClientSocket;

        #endregion

        #region 事件代理方法

        /// <summary>
        /// 显示异常错误信息
        /// </summary>
        /// <param name="aKeyID">异常错误所有者的标志值</param>
        /// <param name="aErrorMessage">异常错误信息</param>
        private void DisplayError(string aKeyID, string aErrorMessage) {
            if (OnSocketError != null) {
                OnSocketError(aKeyID, aErrorMessage);
            }
        }

        /// <summary>
        /// 停止Socket通信之前
        /// </summary>
        /// <param name="aAsyncTCPServer">AsyncTCPServer对象</param>
        private void BeforeStop(AsyncTCPServer aAsyncTCPServer) {
            if (OnBeforeStop != null) {
                OnBeforeStop(aAsyncTCPServer);
            }
        }

        <summary>
        /// 停止Socket通信之后
        /// </summary>
        /// <param name="aAsyncTCPServer">AsyncTCPServer</param>
        private void AfterStop(AsyncTCPServer aAsyncTCPServer) {
            if (OnAfterStop != null) {
                OnAfterStop(aAsyncTCPServer);
            }
        }

        /// <summary>
        /// 接受新的Socket通信连接请求
        /// </summary>
        /// <param name="aNewSocket">新接受的Socket通信连接对象</param>
        public void AcceptClientSocket(Socket aNewSocket) {
            if (OnAcceptClientSocket != null) {
                OnAcceptClientSocket(aNewSocket);
            }
        }

        /// <summary>
        /// 接收二进制数据
        /// </summary>
        /// <param name="aKeyID">接收到数据的Socket标志</param>
        /// <param name="aData">接收到的数据</param>
        /// <param name="aSocket">接收到数据的Socket</param>
        public void BinaryDataAvailable(string aKeyID, byte[] aData, SocketObject aSocketObject) {
            if (OnBinaryDataAvailable != null) {
                OnBinaryDataAvailable(aKeyID, aData, aSocketObject);
            }
        }

        /// <summary>
        /// 接收字符串数据
        /// </summary>
        /// <param name="aKeyID">接收到数据的Socket标志</param>
        /// <param name="aData">接收到的数据</param>
        /// <param name="aSocket">接收到数据的Socket</param>
        public void StringDataAvailable(string aKeyID, string aData, SocketObject aSocketObject) {
            if (OnStringDataAvailable != null) {
                OnStringDataAvailable(aKeyID, aData, aSocketObject);
            }
        }

        /// <summary>
        /// 客户端断开连接
        /// </summary>
        /// <param name="aKeyID">客户端对应的Socket标志</param>
        public void CloseClientSocket(string aKeyID) {
            if (OnCloseClientSocket != null) {
                OnCloseClientSocket(aKeyID);
            }
        }

        #endregion

        #region 内部方法

        /// <summary>
        /// 初始化Socket连接
        /// </summary>
        /// <param name="aLocalIPAddress">本机地址</param>
        /// <param name="aLocalPort">本机端口</param>
        /// <returns>返回操作是否成功</returns>
        private bool InitSocket(string aLocalIPAddress, int aLocalPort) {
            bool bActive = false;
            mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            LingerOption lo = new LingerOption(false, 10);
            mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
            try {
                IPAddress ip = Dns.GetHostAddresses(aLocalIPAddress)[0];
                IPEndPoint ipe = new IPEndPoint(ip, aLocalPort);
                keyID = Guid.NewGuid().ToString();
                mSocket.Bind(ipe);
                bActive = true;
            } catch (Exception ex) {
                bActive = false;
                DisplayError(KeyID, ex.Message);
            }
            return bActive;
        }

        /// <summary>
        /// 监听
        /// </summary>
        /// <param name="aLimitAcceptCount">挂起连接队列的最大长度</param>
        /// <returns>返回操作是否成功</returns>
        private bool Listen(int aLimitAcceptCount) {
            bool bActive = false;
            try {
                if (mSocket != null) {
                    mSocket.Listen(aLimitAcceptCount);
                    //调用异步接收Socket连接请求事件
                    mSocket.BeginAccept(new AsyncCallback(AsyncAcceptSocket), mSocket);
                    bActive = true;
                }
            } catch (Exception ex) {
                bActive = false;
                DisplayError(KeyID, ex.Message);
            }
            return bActive;
        }

        /// <summary>
        /// 主动关闭客户端连接
        /// </summary>
        /// <param name="aSocketObject">客户端对象</param>
        private void CloseClientSocket(SocketObject aSocketObject) {
            try {
                if (aSocketObject.WorkSocket.Connected) {
                    aSocketObject.WorkSocket.Shutdown(SocketShutdown.Both);
                    aSocketObject.WorkSocket.Close();
                    aSocketObject.WorkSocket = null;
                    ClientSocketList.Remove(aSocketObject);
                }
                OnCloseClientSocket(aSocketObject.KeyID);
            } catch (Exception ex) {
                DisplayError(aSocketObject.KeyID, ex.Message);
            }
        }

        /// <summary>
        /// 客户端Socket连接异步接收数据
        /// </summary>
        /// <param name="ar"></param>
        private void AsyncClientSocketReceive(IAsyncResult ar) {
            SocketObject so = (SocketObject)ar.AsyncState;
            try {
                if (so.WorkSocket.Connected) {
                    int iReceiveCount = so.WorkSocket.EndReceive(ar);
                    if (iReceiveCount > 0) {
                        so.sbBuffer.Append(Encoding.UTF8.GetString(so.Buffer, 0, iReceiveCount));
                        string strReceive = so.sbBuffer.ToString();
                        if (strReceive.Substring(strReceive.Length - 1, 1) == EndChar) {
                            //本次接收
                            strReceive = strReceive.Remove(strReceive.Length - 1, 1);
                            //调用外部用户接口方法
                            BinaryDataAvailable(so.KeyID, Encoding.UTF8.GetBytes(strReceive), so);
                            StringDataAvailable(so.KeyID, strReceive, so);
                            //清空数据
                            so.sbBuffer.Remove(0, so.sbBuffer.Length);
                        }
                        if (IsExit == false) {
                            so.WorkSocket.BeginReceive(so.Buffer, 0, so.Buffer.Length, SocketFlags.None, new AsyncCallback(AsyncClientSocketReceive), so);
                        }
                    } else {
                        CloseClientSocket(so);
                    }
                } else {
                    CloseClientSocket(so);
                }
            } catch (Exception ex) {
                //接收数据异常,则关闭该客户端连接
                CloseClientSocket(so);
                DisplayError(so.KeyID, ex.Message);
            }
        }

        /// <summary>
        /// 异步接受Socket连接请求
        /// </summary>
        /// <param name="ar">IAsyncResult接口对象</param>
        private void AsyncAcceptSocket(IAsyncResult ar) {
            Socket sock = (Socket)ar.AsyncState;
            try {
                if (IsExit == false) {
                    Socket handler = sock.EndAccept(ar);
                    AcceptClientSocket(handler);
                    //判断handler是不是被设置为null,如果为null表示连接在执行AcceptSocket过程中用户在OnAcceptSocket中把连接释放掉
                    if (handler != null) {
                        //判断是否保持连接,如果为false,表示连接在执行AcceptSocket过程中用户在OnAcceptSocket中把连接断开掉
                        if (handler.Connected) {
                            SocketObject so = new SocketObject();
                            so.KeyID = Guid.NewGuid().ToString();
                            so.WorkSocket = handler;
                            ClientSocketList.Add(so);
                            if (IsExit == false) {
                                so.WorkSocket.BeginReceive(so.Buffer, 0, so.Buffer.Length, SocketFlags.None, new AsyncCallback(AsyncClientSocketReceive), so);
                            }
                        } else {
                            handler = null;
                        }
                    }
                    if (IsExit == false) {
                        sock.BeginAccept(new AsyncCallback(AsyncAcceptSocket), sock);
                    }
                }
            } catch (Exception ex) {
                //接受连接过程发生异常关闭连接
                Stop();
                DisplayError(KeyID, ex.Message);
            }
        }

        /// <summary>
        /// 通过客户端Socket异步发送消息
        /// </summary>
        /// <param name="ar">IAsyncResult接口对象</param>
        private void AsyncClientSend(IAsyncResult ar) {
            SocketObject so = (SocketObject)ar.AsyncState;
            try {
                int iSendCount = so.WorkSocket.EndSend(ar);
            } catch (Exception ex) {
                DisplayError(so.KeyID, ex.Message);
            }
        }
       
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="aData">要发送的消息</param>
        /// <param name="aSocketObject">接收消息的对象</param>
        private void Send(byte[] aData, SocketObject aSocketObject) {
            try {
                aSocketObject.WorkSocket.BeginSend(aData, 0, aData.Length, SocketFlags.None, new AsyncCallback(AsyncClientSend), aSocketObject);
            } catch (Exception ex) {
                DisplayError(aSocketObject.KeyID, ex.Message);
            }
        }

        #endregion

        #region 开放的接口方法

        /// <summary>
        /// 启动Socket通信
        /// </summary>
        /// <param name="aLocalIPAddress">本机地址</param>
        /// <param name="aLocalPort">本机端口</param>
        /// <param name="aLimitAcceptCount">挂起连接队列的最大长度</param>
        /// <returns>返回操作是否成功</returns>
        public bool Start(string aLocalIPAddress, int aLocalPort, int aLimitAcceptCount) {
            bool bActive = InitSocket(aLocalIPAddress, aLocalPort);
            if (bActive) {
                bActive = Listen(aLimitAcceptCount);
            }
            active = bActive;
            return active;
        }

        /// <summary>
        /// 停止Socket通信
        /// </summary>
        /// <returns>返回操作是否成功</returns>
        public bool Stop() {
            bool bActive = false;
            if (mSocket != null) {
                //之前
                BeforeStop(this);
                try {
                    IsExit = true;
                    Thread.Sleep(10);
                    if (mSocket.Connected) {
                        mSocket.Shutdown(SocketShutdown.Both);
                    }
                    mSocket.Close();
                    mSocket = null;
                    bActive = true;

                } catch (Exception ex) {
                    bActive = false;
                    DisplayError(KeyID, ex.Message);
                }
                active = !bActive;
                //之后
                if (bActive) {
                    AfterStop(this);
                }
            }
            return bActive;
        }

        /// <summary>
        /// 发送消息(异步发送)
        /// </summary>
        /// <param name="aMessage">要发送的消息</param>
        public void Send(string aMessage, SocketObject aSocketObject) {
            string strMessage = aMessage;
            //判断要发送的消息是不是以消息终止判断符号结尾,如果没有则自动加上
            if (strMessage.Substring(strMessage.Length - 1, 1) != EndChar) {
                strMessage = strMessage + EndChar;
            }
            Send(Encoding.UTF8.GetBytes(strMessage), aSocketObject);
        }

        /// <summary>
        /// 发送消息(异步发送)
        /// </summary>
        /// <param name="aMessage">要发送的消息</param>
        public void Send(byte[] aMessage, int aMessageLength, SocketObject aSocketObject) {
            StringBuilder SendBuffer = new StringBuilder();
            SendBuffer.Append(Encoding.UTF8.GetString(aMessage, 0, aMessageLength));
            string strSend = SendBuffer.ToString();
            Send(strSend, aSocketObject);
        }

        /// <summary>
        /// 广播消息
        /// </summary>
        /// <param name="aMessage">要广播的消息</param>
        public void BroadcastMessage(string aMessage) {
            string strMessage = aMessage;
            //判断要发送的消息是不是以消息终止判断符号结尾,如果没有则自动加上
            if (strMessage.Substring(strMessage.Length - 1, 1) != EndChar) {
                strMessage = strMessage + EndChar;
            }
            for (int i = 0; i < ClientSocketList.Count; i++) {
                SocketObject so = (SocketObject)ClientSocketList[i];
                try {
                    Send(Encoding.UTF8.GetBytes(strMessage), so);
                } catch (Exception ex) {
                    DisplayError(so.KeyID, ex.Message);
                }
            }
        }

        #endregion
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值