NetPushClient.cs 5.83 KB
using HslCommunication.Core.Net;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace HslCommunication.Enthernet
{

    /// <summary>
    /// 发布订阅类的客户端,使用指定的关键订阅相关的数据推送信息
    /// </summary>
    /// <remarks>
    /// 详细的使用说明,请参照博客<a href="http://www.cnblogs.com/dathlin/p/8992315.html">http://www.cnblogs.com/dathlin/p/8992315.html</a>
    /// </remarks>
    /// <example>
    /// 此处贴上了Demo项目的服务器配置的示例代码
    /// <code lang="cs" source="TestProject\HslCommunicationDemo\FormPushNet.cs" region="FormPushNet" title="NetPushClient示例" />
    /// </example>
    public class NetPushClient : NetworkXBase
    {
        #region Constructor

        /// <summary>
        /// 实例化一个发布订阅类的客户端,需要指定ip地址,端口,及订阅关键字
        /// </summary>
        /// <param name="ipAddress">服务器的IP地址</param>
        /// <param name="port">服务器的端口号</param>
        /// <param name="key">订阅关键字</param>
        public NetPushClient(string ipAddress, int port, string key)
        {
            endPoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
            keyWord = key;

            if (string.IsNullOrEmpty(key))
            {
                throw new Exception(StringResources.Language.KeyIsNotAllowedNull);
            }
        }

        #endregion

        #region NetworkXBase Override

        internal override void DataProcessingCenter(AppSession session, int protocol, int customer, byte[] content)
        {
            if (protocol == HslProtocol.ProtocolUserString)
            {
                action?.Invoke(this, Encoding.Unicode.GetString(content));
                OnReceived?.Invoke(this, Encoding.Unicode.GetString(content));
            }
        }

        internal override void SocketReceiveException(AppSession session, Exception ex)
        {
            // 发生异常的时候需要进行重新连接
            while (true)
            {
                Console.WriteLine(ex);
                Console.WriteLine(StringResources.Language.ReConnectServerAfterTenSeconds);
                System.Threading.Thread.Sleep(this.reconnectTime);

                if (CreatePush().IsSuccess)
                {
                    Console.WriteLine(StringResources.Language.ReConnectServerSuccess);
                    break;
                }
            }
        }

        #endregion

        #region Public Method 

        /// <summary>
        /// 创建数据推送服务
        /// </summary>
        /// <param name="pushCallBack">触发数据推送的委托</param>
        /// <returns>是否创建成功</returns>
        public OperateResult CreatePush(Action<NetPushClient, string> pushCallBack)
        {
            action = pushCallBack;
            return CreatePush();
        }

        /// <summary>
        /// 创建数据推送服务,使用事件绑定的机制实现
        /// </summary>
        /// <returns>是否创建成功</returns>
        public OperateResult CreatePush()
        {
            CoreSocket?.Close();

            // 连接服务器
            OperateResult<Socket> connect = CreateSocketAndConnect(endPoint, 5000);
            if (!connect.IsSuccess) return connect;

            // 发送订阅的关键字
            OperateResult send = SendStringAndCheckReceive(connect.Content, 0, keyWord);
            if (!send.IsSuccess) return send;

            // 确认服务器的反馈
            OperateResult<int, string> receive = ReceiveStringContentFromSocket(connect.Content);
            if (!receive.IsSuccess) return receive;

            // 订阅不存在
            if (receive.Content1 != 0)
            {
                connect.Content?.Close();
                return new OperateResult(receive.Content2);
            }

            // 异步接收
            AppSession appSession = new AppSession();
            CoreSocket = connect.Content;
            appSession.WorkSocket = connect.Content;
            ReBeginReceiveHead(appSession, false);

            return OperateResult.CreateSuccessResult();
        }

        /// <summary>
        /// 关闭消息推送的界面
        /// </summary>
        public void ClosePush()
        {
            action = null;
            if (CoreSocket != null && CoreSocket.Connected) CoreSocket?.Send(BitConverter.GetBytes(100));
            System.Threading.Thread.Sleep(20);
            CoreSocket?.Close();
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// 本客户端的关键字
        /// </summary>
        public string KeyWord => keyWord;

        /// <summary>
        /// 获取或设置重连服务器的间隔时间
        /// </summary>
        public int ReConnectTime { set => reconnectTime = value; get => reconnectTime; }

        #endregion

        #region Public Event

        /// <summary>
        /// 当接收到数据的事件信息,接收到数据的时候触发。
        /// </summary>
        public event Action<NetPushClient, string> OnReceived;

        #endregion

        #region Private Member

        private IPEndPoint endPoint;                           // 服务器的地址及端口信息
        private string keyWord = string.Empty;                 // 缓存的订阅关键字
        private Action<NetPushClient, string> action;          // 服务器推送后的回调方法
        private int reconnectTime = 10000;                     // 重连服务器的时间

        #endregion

        #region Object Override

        /// <summary>
        /// 返回表示当前对象的字符串
        /// </summary>
        /// <returns>字符串</returns>
        public override string ToString()
        {
            return $"NetPushClient[{endPoint}]";
        }

        #endregion
    }
}