Files
6078/src/StandardDomeNewApp/Communication/Sockets/SingleSocketServer.cs

451 lines
17 KiB
C#
Raw Normal View History

using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace StandardDomeNewApp.Communication.Sockets
{
public class SingleSocketServer
{
public SingleSocketServer(string encoding = null)
{
this.encoding = string.IsNullOrEmpty(encoding) ? Encoding.Default : Encoding.GetEncoding(encoding);
}
/// <summary>
/// 服务类型 1是supersocket 2是iocp
/// </summary>
private int serverType { set; get; }
/// <summary>
/// 解码方式
/// </summary>
public Encoding encoding { private set; get; }
/// <summary>
/// 服务对象
/// </summary>
private AppServer appServer { set; get; }
/// <summary>
///
/// </summary>
private socket.core.Server.TcpPushServer iocpServer { set; get; }
/// <summary>
///
/// </summary>
private Regex regex { set; get; } = new Regex(@"^%.*|.*%$");
/// <summary>
/// 会话字典
/// </summary>
public Dictionary<string, string> SessionIDDic { private set; get; } = new Dictionary<string, string>();
/// <summary>
/// 消息委托
/// </summary>
public Action<string, bool, Core.SysEnumInfon.MessageLogType> ShowMessageAction { set; get; }
/// <summary>
/// 接收消息委托 二进制数组的
/// </summary>
public Action<string, string> RequestReceivedAction { set; get; }
/// <summary>
/// 会话进来
/// </summary>
public Action<string> OnSessionAccept { set; get; }
/// <summary>
/// 会话结束
/// </summary>
public Action<string> OnSessionClose { set; get; }
public bool IsOpenServer { private set; get; }
public string ServerName { private set; get; }
/// <summary>
/// 是否允许接收字典
/// </summary>
public ConcurrentDictionary<string, bool> IsAllowReceiveDic { set; get; } = new ConcurrentDictionary<string, bool>();
/// <summary>
/// 会话数据字典
/// </summary>
public ConcurrentDictionary<string, string> SessionDataDic { set; get; } = new ConcurrentDictionary<string, string>();
#region
/// <summary>
/// 启动服务
/// </summary>
/// <param name="port">服务端口</param>
/// <param name="enddata">servertype为2时才有意义 结尾符</param>
public void StartServer(string serverkey, int port, byte[] enddata = null)
{
ServerName = serverkey;
if (enddata == null)
{
//当为空时使用iocp的方式
serverType = 2;
iocpServer = new socket.core.Server.TcpPushServer(100, 1024 * 2, 0);
if (ushort.TryParse(port.ToString(), out ushort port2))
{
try
{
iocpServer.Start(port);
}
catch (Exception ex)
{
ShowMessageAction?.Invoke("启动失败!" + ex.Message, false, Core.SysEnumInfon.MessageLogType.Warn);
}
IsOpenServer = true;
iocpServer.OnAccept += IocpServer_OnAccept;
iocpServer.OnClose += IocpServer_OnClose;
iocpServer.OnReceive += IocpServer_OnReceive;
}
else
{
ShowMessageAction?.Invoke("端口输入范围在0-65535的值", false, Core.SysEnumInfon.MessageLogType.Warn);
}
return;
}
//使用supersocket组件
serverType = 1;
if (enddata.Length < 1)
{
appServer = new AppServer();
}
else
{
appServer = new AppServer(new TerminatorReceiveFilterFactory(encoding.GetString(enddata)));
}
appServer.NewRequestReceived += AppServer_NewRequestReceived;
appServer.NewSessionConnected += AppServer_NewSessionConnected;
appServer.SessionClosed += AppServer_SessionClosed;
var serverconfig = new SuperSocket.SocketBase.Config.ServerConfig();
serverconfig.Port = port;
serverconfig.TextEncoding = encoding.EncodingName;
if (ushort.TryParse(port.ToString(), out ushort port1))
{
if (!appServer.Setup(serverconfig))
{
ShowMessageAction?.Invoke("设置错误!", false, Core.SysEnumInfon.MessageLogType.Warn);
return;
}
if (!appServer.Start())
{
ShowMessageAction?.Invoke("启动失败!", false, Core.SysEnumInfon.MessageLogType.Warn);
return;
}
IsOpenServer = true;
}
else
{
ShowMessageAction?.Invoke("端口输入范围在0-65535的值", false, Core.SysEnumInfon.MessageLogType.Warn);
}
}
/// <summary>
/// 结束服务
/// </summary>
public void StopServer()
{
if (!IsOpenServer)
{
ShowMessageAction?.Invoke("当前状态不需要断开监听!", false, Core.SysEnumInfon.MessageLogType.Info);
return;
}
if (serverType == 1)
{
appServer.Stop();
appServer.Dispose();
appServer = null;
}
else if (serverType == 2)
{
var dic = new Dictionary<int, string>(iocpServer.ClientList);
foreach (var item in dic)
{
iocpServer.Close(item.Key);
}
}
IsOpenServer = false;
}
/// <summary>
/// 会话发送
/// </summary>
/// <param name="datas"></param>
/// <param name="sessionid">为空时为广播</param>
public void SessionSend(byte[] datas, string sessionid = null)
{
if (datas == null || datas.Length < 1)
{
ShowMessageAction?.Invoke("数据为空,无效发送!", false, Core.SysEnumInfon.MessageLogType.Info);
return;
}
if (string.IsNullOrEmpty(sessionid))
{
if (serverType == 1)
{
var allsessions = appServer.GetAllSessions();
foreach (var item in allsessions)
{
item.Send(encoding.GetString(datas));
}
}
else if (serverType == 2)
{
foreach (var item in iocpServer.ClientList)
{
iocpServer.Send(item.Key, datas, 0, datas.Length);
}
}
}
else
{
if (serverType == 1)
{
var one = appServer.GetSessionByID(sessionid);
if (one != null)
{
one.Send(encoding.GetString(datas));
}
else
{
ShowMessageAction?.Invoke("请检查传入的会话ID是否有效当前无法查询到相关会话信息无效发送", false, Core.SysEnumInfon.MessageLogType.Info);
}
}
else if (serverType == 2)
{
if (int.TryParse(sessionid, out int num) && iocpServer.ClientList.ContainsKey(num))
{
iocpServer.Send(num, datas, 0, datas.Length);
}
else
{
ShowMessageAction?.Invoke("请检查传入的会话ID是否有效当前无法查询到相关会话信息无效发送", false, Core.SysEnumInfon.MessageLogType.Info);
}
}
}
}
/// <summary>
/// 会话发送
/// </summary>
/// <param name="datas"></param>
/// <param name="sessionid">为空时为广播</param>
public void SessionSend(string datas, string sessionid = null)
{
if (string.IsNullOrEmpty(datas))
{
ShowMessageAction?.Invoke("数据为空,无效发送!", false, Core.SysEnumInfon.MessageLogType.Info);
return;
}
if (string.IsNullOrEmpty(sessionid))
{
if (serverType == 1)
{
var allsessions = appServer.GetAllSessions();
foreach (var item in allsessions)
{
item.Send(datas);
}
}
else if (serverType == 2)
{
foreach (var item in iocpServer.ClientList)
{
iocpServer.Send(item.Key, encoding.GetBytes(datas), 0, datas.Length);
}
}
}
else
{
if (serverType == 1)
{
var one = appServer.GetSessionByID(sessionid);
if (one != null)
{
one.Send(datas);
}
else
{
ShowMessageAction?.Invoke("请检查传入的会话ID是否有效当前无法查询到相关会话信息无效发送", false, Core.SysEnumInfon.MessageLogType.Info);
}
}
else if (serverType == 2)
{
if (int.TryParse(sessionid, out int num) && iocpServer.ClientList.ContainsKey(num))
{
iocpServer.Send(num, encoding.GetBytes(datas), 0, datas.Length);
}
else
{
ShowMessageAction?.Invoke("请检查传入的会话ID是否有效当前无法查询到相关会话信息无效发送", false, Core.SysEnumInfon.MessageLogType.Info);
}
}
}
}
/// <summary>
/// 返回地址对应的sessionid 可能返回为空
/// </summary>
/// <param name="ipaddress"></param>
/// <returns></returns>
public string GetSessionID(string ipaddress)
{
string sessionid = null;
var datas = SessionIDDic.Where(d => d.Value == ipaddress);
if (datas != null)
{
var list = datas.ToList();
if (list.Count > 0)
{
var oneitem = list.ElementAt(0);
sessionid = oneitem.Key;
}
}
return sessionid;
}
/// <summary>
/// 返回id对应的地址 可能返回为空
/// </summary>
/// <param name="sessionid"></param>
/// <returns></returns>
public string GetIpAddress(string sessionid)
{
if (SessionIDDic.ContainsKey(sessionid))
{
return SessionIDDic[sessionid];
}
return null;
}
#endregion
#region
/// <summary>
/// 会话关闭
/// </summary>
/// <param name="session"></param>
/// <param name="value"></param>
private void AppServer_SessionClosed(AppSession session, CloseReason value)
{
if (SessionIDDic.ContainsKey(session.SessionID))
{
SessionIDDic.Remove(session.SessionID);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("会话:");
stringBuilder.Append(session.SessionID);
stringBuilder.Append("(");
stringBuilder.Append(session.RemoteEndPoint.Address);
stringBuilder.Append(":");
stringBuilder.Append(session.RemoteEndPoint.Port.ToString());
stringBuilder.Append(")");
stringBuilder.Append("关闭!关闭原因:");
stringBuilder.Append(value.ToString());
ShowMessageAction?.Invoke(stringBuilder.ToString(), false, Core.SysEnumInfon.MessageLogType.Info);
OnSessionClose?.Invoke(session.SessionID);
}
}
private void IocpServer_OnClose(int obj)
{
if (SessionIDDic.ContainsKey(obj.ToString()))
{
SessionIDDic.Remove(obj.ToString());
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("会话:");
stringBuilder.Append(obj.ToString());
stringBuilder.Append("(");
if (iocpServer.ClientList.ContainsKey(obj))
{
stringBuilder.Append(iocpServer.ClientList[obj]);
}
stringBuilder.Append(")");
stringBuilder.Append("关闭!关闭原因:用户退出!");
ShowMessageAction?.Invoke(stringBuilder.ToString(), false, Core.SysEnumInfon.MessageLogType.Info);
OnSessionClose?.Invoke(obj.ToString());
}
}
/// <summary>
/// 会话新连接
/// </summary>
/// <param name="session"></param>
private void AppServer_NewSessionConnected(AppSession session)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(session.RemoteEndPoint.Address);
stringBuilder.Append(":");
stringBuilder.Append(session.RemoteEndPoint.Port.ToString());
string info = stringBuilder.ToString();
//记录会话id与物理地址的关系
SessionIDDic[session.SessionID] = info;
stringBuilder.Remove(0, stringBuilder.Length);
stringBuilder.Append("新进会话:");
stringBuilder.Append(session.SessionID);
stringBuilder.Append("(");
stringBuilder.Append(info);
stringBuilder.Append(")");
ShowMessageAction?.Invoke(stringBuilder.ToString(), false, Core.SysEnumInfon.MessageLogType.Info);
OnSessionAccept?.Invoke(session.SessionID);
}
/// <summary>
/// 新的会话进来
/// </summary>
/// <param name="obj"></param>
private void IocpServer_OnAccept(int obj)
{
StringBuilder stringBuilder = new StringBuilder();
if (!iocpServer.ClientList.ContainsKey(obj))
{
return;
}
stringBuilder.Append(iocpServer.ClientList[obj]);
string info = stringBuilder.ToString();
//记录会话id与物理地址的关系
SessionIDDic[obj.ToString()] = info;
stringBuilder.Remove(0, stringBuilder.Length);
stringBuilder.Append("新进会话:");
stringBuilder.Append(obj.ToString());
stringBuilder.Append("(");
stringBuilder.Append(info);
stringBuilder.Append(")");
ShowMessageAction?.Invoke(stringBuilder.ToString(), false, Core.SysEnumInfon.MessageLogType.Info);
OnSessionAccept?.Invoke(obj.ToString());
}
/// <summary>
/// 会话信息接收
/// </summary>
/// <param name="session"></param>
/// <param name="requestInfo"></param>
private void AppServer_NewRequestReceived(AppSession session, StringRequestInfo requestInfo)
{
var sessionid = session.SessionID;
var bdatas = requestInfo.Key + "%" + requestInfo.Body;
if (string.IsNullOrEmpty(bdatas))
{
//空数据不解析
return;
}
if (regex.IsMatch(bdatas))
{
//如果有%在头或者尾
bdatas = bdatas.Replace("%", "").Trim();
}
RequestReceivedAction(sessionid, bdatas);
}
/// <summary>
/// 接收消息
/// </summary>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
private void IocpServer_OnReceive(int arg1, byte[] arg2)
{
RequestReceivedAction(arg1.ToString(), encoding.GetString(arg2));
}
#endregion
}
}