编写TCP异步通信组件之AsyncTCPClient

来源:互联网 发布:centos yum pip 编辑:程序博客网 时间:2024/06/11 10:27

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

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

namespace SocketLibrary {
    public partial class AsyncTCPClient : Component {

        #region 构造函数

        public AsyncTCPClient() {
            InitializeComponent();
        }

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

            InitializeComponent();
        }

        #endregion

        #region 变量

        private Socket mSocket = null;
        private string localIPAddress = "";
        private int localPort = 0;
        private string remoteIPAddress = "";
        private int remotePort = 0;
        private string keyID = "";
        private bool IsExit = false;
        private SocketObject so = new SocketObject();

        #endregion

        #region 变量属性

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

        /// <summary>
        /// 本机地址
        /// </summary>
        public string LocalIPAddress {
            get {
                return localIPAddress;
            }
        }

        /// <summary>
        /// 本机端口
        /// </summary>
        public int LocalPort {
            get {
                return localPort;
            }
        }

        /// <summary>
        /// 主机地址
        /// </summary>
        public string RemoteIPAddress {
            get {
                return remoteIPAddress;
            }
        }

        /// <summary>
        /// 主机端口
        /// </summary>
        public int RemotePort {
            get {
                return remotePort;
            }
        }

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

        #endregion

        #region 代理委托

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

        /// <summary>
        /// 接收二进制数据
        /// </summary>
        /// <param name="aData">接收到的数据</param>
        public delegate void BinaryDataAvailableHandler(byte[] aData);

        /// <summary>
        /// 接收字符串数据
        /// </summary>
        /// <param name="aData">接收到的数据</param>
        public delegate void StringDataAvailableHandler(string aData);

        #endregion

        #region 事件声明

        public event SocketErrorHandler OnSocketError;
        public event BinaryDataAvailableHandler OnBinaryDataAvailable;
        public event StringDataAvailableHandler OnStringDataAvailable;

        #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>
        /// 接收二进制数据
        /// </summary>
        /// <param name="aData">接收到的数据</param>
        private void BinaryDataAvailable(byte[] aData) {
            if (OnBinaryDataAvailable != null) {
                OnBinaryDataAvailable(aData);
            }
        }

        /// <summary>
        /// 接收字符串数据
        /// </summary>
        /// <param name="aData">接收到的数据</param>
        private void StringDataAvailable(string aData) {
            if (OnStringDataAvailable != null) {
                OnStringDataAvailable(aData);
            }
        }

        #endregion

        #region 内部方法

        /// <summary>
        /// 异步接收数据
        /// </summary>
        /// <param name="ar">IAsyncResult接口对象</param>
        private void AsyncDataReceive(IAsyncResult ar) {
            SocketObject so = (SocketObject)ar.AsyncState;
            try {
                if (IsExit == false) {
                    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(Encoding.UTF8.GetBytes(strReceive));
                            StringDataAvailable(strReceive);
                            //清空数据
                            so.sbBuffer.Remove(0, so.sbBuffer.Length);
                        }
                        if (IsExit == false) {
                            so.WorkSocket.BeginReceive(so.Buffer, 0, so.Buffer.Length, SocketFlags.None, new AsyncCallback(AsyncDataReceive), so);
                        }
                    } else {
                        Disconnect();
                    }
                } else {
                    Disconnect();
                }
            } catch (Exception ex) {
                DisplayError(KeyID, ex.Message);
            }
        }

        /// <summary>
        /// 异步发送消息
        /// </summary>
        /// <param name="ar">IAsyncResult接口对象</param>
        private void AsyncSend(IAsyncResult ar) {
            try {
                int iSendCount = mSocket.EndSend(ar);
            } catch (Exception ex) {
                DisplayError(KeyID, ex.Message);
            }
        }

        /// <summary>
        /// 发送消息(异步发送)
        /// </summary>
        /// <param name="aData">要发送的消息</param>
        private void Send(byte[] aData) {
            try {
                mSocket.BeginSend(aData, 0, aData.Length, SocketFlags.None, new AsyncCallback(AsyncSend), null);
            } catch (Exception ex) {
                DisplayError(KeyID, ex.Message);
            }
        }

        private void AsyncConnect(IAsyncResult ar) {
            Socket sock = (Socket)ar.AsyncState;
            try {
                sock.EndConnect(ar);
                if (sock.Connected) {
                    //启动消息接收事件
                    so.KeyID = KeyID;
                    so.WorkSocket = sock;
                    if (IsExit == false) {
                        so.WorkSocket.BeginReceive(so.Buffer, 0, so.Buffer.Length, SocketFlags.None, new AsyncCallback(AsyncDataReceive), so);
                    }
                } else {
                    new Exception("Unable to connect to remote machine, Connect Failed!");
                }
            } catch (Exception ex) {
                DisplayError(KeyID, ex.Message);
            }
        }

        #endregion

        #region 对外开发的接口方法

        /// <summary>
        /// 初始化本机Socket通信机制
        /// </summary>
        /// <param name="aLocalIPAddress">本机地址</param>
        /// <param name="aLocalPort">本机端口</param>
        /// <returns>返回操作是否成功</returns>
        public 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];
                if (aLocalPort == 0) {
                    Random rd = new Random(5000);
                    aLocalPort = rd.Next(30000);
                }
                localIPAddress = ip.ToString();
                localPort = aLocalPort;
                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="aRemoteIPAddress">主机地址</param>
        /// <param name="aRemotePort">主机端口</param>
        /// <returns>返回操作是否成功</returns>
        public bool Connect(string aRemoteIPAddress, int aRemotePort) {
            if (mSocket == null)
                return false;
            try {
                remoteIPAddress = aRemoteIPAddress;
                remotePort = aRemotePort;
                mSocket.Blocking = false;
                mSocket.BeginConnect(remoteIPAddress, remotePort, new AsyncCallback(AsyncConnect), mSocket);
            } catch (Exception ex) {
                DisplayError(KeyID, ex.Message);
            }
            return mSocket.Connected;
        }

        /// <summary>
        /// 断开与主机的连接
        /// </summary>
        /// <returns></returns>
        public bool Disconnect() {
            try {
                if (mSocket != null) {
                    if (mSocket.Connected) {
                        mSocket.Shutdown(SocketShutdown.Both);
                        mSocket.Close();
                        mSocket = null;
                    } else {
                        mSocket = null;
                    }
                }
                return true;
            } catch (Exception ex) {
                DisplayError(keyID, ex.Message);
                return false;
            }
        }

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

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

        #endregion
    }
}
 

原创粉丝点击