You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
6.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HslCommunication.Core.Net;
using System.Net;
using System.Net.Sockets;
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
}
}