提交 e6bdda5f 编写于 作者: JasonWcx's avatar JasonWcx

修改Reame

上级 83c13b84
# Mozi.HttpEmbedded 嵌入式Web服务器
Mozi.HttpEmbedded是一个基于.Net构建的嵌入式HTTP服务器,为.Net App提供web服务功能。
Mozi.HttpEmbedded是一个基于.Net构建的嵌入式HTTP服务器,为.Net应用提供HTTP服务功能。
> 嵌入式的目标不是单片机,而是.Net应用程序。
> 此项目并不会实现非常丰富的大型Web服务器功能
......@@ -74,6 +74,10 @@ Mozi.HttpEmbedded在Socket之上使用异步单线程模型,构建了一个HTTP
dotnet add package Mozi.HttpEmbedded --version 1.2.5
~~~
## 项目依赖
## 功能与版本迭代
不定期对Mozi.HttpEmbedded的功能进行完善,解决各种BUG。HTTP标准功能繁多,需要一步步实现。
......
# Mozi.SSDP
Mozi.SSDP是一个基于.Net开发的SSDP服务组件,目标是为.Net应用程序提供完善的SSDP服务功能。 项目对UDP Socket进行封装,并遵循UPNP/2.0(UPnP Device Architecture 2.0),实现了UPNP2.0规范中的大部分功能。
### 项目简介
## 功能特性
Mozi.SSDP是一个基于.Net开发的SSDP组件,目标是为.Net应用程序提供完善的SSDP/UPNP服务功能。 项目对UDP Socket进行封装,并遵循UPNP/2.0(UPnP Device Architecture 2.0),实现了UPNP2.0规范中的大部分功能。
## 特点
1. 精巧
2. 高度可控
3. 依赖少,仅依赖于HTTP服务器组件[HttpEmbedded][httpembedded]
## 功能
1. 发现-在线
- 在线通知
......@@ -11,9 +19,10 @@ Mozi.SSDP是一个基于.Net开发的SSDP服务组件,目标是为.Net应用
- 更新
3. 设备和服务描述
内含设备和服务描述文档,使用过程中请自行填写和发布
3. 控制
4. 事件
## 项目地址
......@@ -28,7 +37,7 @@ Mozi.SSDP是一个基于.Net开发的SSDP服务组件,目标是为.Net应用
~~~shell
dotnet add package Mozi.SSDP --version 1.2.5
dotnet add package Mozi.SSDP --version 1.2.6
~~~
## 项目依赖
......
......@@ -5,6 +5,7 @@ namespace Mozi.StateService.Test
class Program
{
static readonly HeartBeatGateway hg = new HeartBeatGateway();
static readonly HeartBeatSubscriber hbs = new HeartBeatSubscriber();
static void Main(string[] args)
{
......@@ -13,7 +14,7 @@ namespace Mozi.StateService.Test
//HeartBeatService state = new HeartBeatService()
//{
// Port = 13453,
// RemoteHost = $"{host}"
// RemoteHost = $"100.100.0.111"
//};
//state.ApplyDevice("Mozi", "80018001", "1.2.3");
......@@ -23,13 +24,21 @@ namespace Mozi.StateService.Test
//state.SetState(ClientLifeState.Idle);
//服务网关
hg.AddSubscriber(new Subscriber() { Host = "100.100.0.171", Port = 13452 });
hg.OnClientOnlineStateChange += Hg_OnClientStateChange;
hg.OnClientMessageReceive += Hg_OnClientMessageReceive;
hg.OnClientUserChange += Hg_OnClientUserChange;
hg.OnClientJoin += Hg_OnClientJoin;
hg.OnClientLifeStateChange += Hg_OnClientLifeStateChange;
hg.Start(13453);
hbs.OnClientOnlineStateChange += Hg_OnClientStateChange;
hbs.OnClientMessageReceive += Hg_OnClientMessageReceive;
hbs.OnClientUserChange += Hg_OnClientUserChange;
hbs.OnClientJoin += Hg_OnClientJoin;
hbs.OnClientLifeStateChange += Hg_OnClientLifeStateChange;
hbs.Start(13452);
Console.ReadLine();
}
/// <summary>
......
......@@ -82,19 +82,19 @@ namespace Mozi.StateService
/// <summary>
/// 终端通知状态变更
/// </summary>
public event ClientLifeStateChange OnClientLifeStateChange;
public ClientLifeStateChange OnClientLifeStateChange;
/// <summary>
/// 终端在线状态变更事件
/// </summary>
public event ClientOnlineStateChange OnClientOnlineStateChange;
public ClientOnlineStateChange OnClientOnlineStateChange;
/// <summary>
/// 终端在线用户变更
/// </summary>
public event ClientUserChange OnClientUserChange;
public ClientUserChange OnClientUserChange;
/// <summary>
/// 终端消息接收事件
/// </summary>
public event ClientMessageReceive OnClientMessageReceive;
public ClientMessageReceive OnClientMessageReceive;
/// <summary>
/// 终端列表
/// </summary>
......@@ -324,7 +324,7 @@ namespace Mozi.StateService
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void _socket_AfterReceiveEnd(object sender, DataTransferArgs args)
protected virtual void _socket_AfterReceiveEnd(object sender, DataTransferArgs args)
{
try
{
......@@ -343,7 +343,7 @@ namespace Mozi.StateService
{
OnClientMessageReceive.BeginInvoke(this, client,args.IP,args.Port, null, null);
}
PostMessageToSubscribers(ref args);
PostMessageToSubscribers(args.IP,args.Port,pg);
}
catch(Exception ex)
{
......@@ -351,14 +351,20 @@ namespace Mozi.StateService
}
}
private void PostMessageToSubscribers(ref DataTransferArgs args)
protected virtual void PostMessageToSubscribers(string srcHost,int srcPort,HeartBeatPackage pg)
{
foreach (var sub in Subscribers)
{
try
{
HeartBeatPublishPackage hbp = new HeartBeatPublishPackage()
{
SrcHost = srcHost,
SrcPort = (ushort)srcPort,
HeartBeat = pg
};
//域过滤
_socket.SocketMain.SendTo(args.Data,new IPEndPoint(IPAddress.Parse(sub.Host), sub.Port));
_socket.SocketMain.SendTo(hbp.Pack(),new IPEndPoint(IPAddress.Parse(sub.Host), sub.Port));
}catch(Exception ex){
}
......
......@@ -209,7 +209,7 @@ namespace Mozi.StateService
{
Version = data[0]
};
int hostLength = BitConverter.ToUInt16(data, 1);
ushort hostLength = BitConverter.ToUInt16(data, 1);
byte[] byteHost = new byte[hostLength];
Array.Copy(data, 1 +2, byteHost, 0, hostLength);
pack.SrcHost = byteHost.AsString();
......
......@@ -4,270 +4,39 @@ using System.Collections.Generic;
namespace Mozi.StateService
{
/// <summary>
/// 心跳网关服务器
/// 心跳订阅者 订阅者为已知订阅者
/// </summary>
public class HeartBeatSubscriber
public class HeartBeatSubscriber:HeartBeatGateway
{
private readonly UDPSocket _socket;
private int _timeoutOffline = 180;
private int _port = 13452;
private List<ClientAliveInfo> _clients = new List<ClientAliveInfo>();
/// <summary>
/// 服务端端口
/// </summary>
public int Port { get { return _port; } }
public DateTime StartTime { get; private set; }
/// <summary>
/// 终端加入事件
/// </summary>
public event ClientJoinQuit OnClientJoin;
/// <summary>
/// 终端通知状态变更
/// </summary>
public event ClientLifeStateChange OnClientLifeStateChange;
/// <summary>
/// 终端在线状态变更事件
/// </summary>
public event ClientOnlineStateChange OnClientOnlineStateChange;
/// <summary>
/// 终端在线用户变更
/// </summary>
public event ClientUserChange OnClientUserChange;
/// <summary>
/// 终端消息接收事件
/// </summary>
public event ClientMessageReceive OnClientMessageReceive;
/// <summary>
/// 终端列表
/// </summary>
public List<ClientAliveInfo> Clients { get { return _clients; } }
/// <summary>
/// 订阅者列表
/// </summary>
public List<Subscriber> Subscribers = new List<Subscriber>();
/// <summary>
/// 是否开启统计
/// </summary>
public bool EnableCount { get; set; }
/// <summary>
/// 统计
/// </summary>
public ClientStateStatistics Statistics = new ClientStateStatistics();
public HeartBeatSubscriber()
{
_socket = new UDPSocket();
_socket.AfterReceiveEnd += _socket_AfterReceiveEnd;
}
/// <summary>
/// 以默认端口启动<see cref="F:Port"/>
/// </summary>
public void Start()
{
Start(_port);
}
/// <summary>
/// 启动网关
/// </summary>
/// <param name="port"></param>
public void Start(int port)
{
_port = port;
_socket.Start(_port);
StartTime = DateTime.Now;
}
/// <summary>
/// 网关下线
/// </summary>
public void Shutdown()
{
_socket.Shutdown();
StartTime = DateTime.MinValue;
}
/// <summary>
/// 设置用户名
/// </summary>
/// <param name="client"></param>
/// <param name="userName"></param>
public void SetUserName(ref ClientAliveInfo client, string userName)
{
if (client != null)
{
var clientOldUserName = client.UserName;
client.UserName = userName;
if (client.UserName != clientOldUserName && OnClientUserChange != null)
{
try
{
//触发终端状态变更事件
OnClientUserChange.BeginInvoke(this, client, clientOldUserName, client.UserName, null, null);
}
finally
{
}
}
}
}
/// <summary>
/// 刷新终端心跳状态
/// </summary>
/// <param name="client"></param>
/// <param name="state"></param>
private void SetClientLifeState(ref ClientAliveInfo client, ClientLifeState state)
{
if (client != null)
{
var clientOldState = client.State;
client.State = state;
if (client.State != clientOldState && OnClientLifeStateChange != null)
{
try
{
//触发终端状态变更事件
OnClientLifeStateChange.BeginInvoke(this, client, clientOldState, client.State, null, null);
}
finally
{
}
}
//开启统计功能
if (EnableCount)
{
Statistics.UpdateClientLiftState(client, state);
}
}
}
/// <summary>
/// 设置终端状态
/// <para>
/// 如非必要不要调用这个方法
/// </para>
/// </summary>
/// <param name="ca"></param>
/// <param name="state"></param>
public void SetClientState(ClientAliveInfo ca, ClientOnlineState state)
{
var client = _clients.Find(x => x.DeviceName.Equals(ca.DeviceName) && x.DeviceId.Equals(ca.DeviceId));
if (client != null)
{
var clientOldState = client.ClientState;
client.ClientState = state;
if (client.ClientState != clientOldState && OnClientOnlineStateChange != null)
{
try
{
//触发终端在线状态变更事件
OnClientOnlineStateChange.BeginInvoke(this, client, clientOldState, client.ClientState, null, null);
}
finally
{
}
}
}
}
/// <summary>
/// 将终端置于失效状态
/// <para>若终端长时间无心跳包,可将终端标记为已不可用</para>
/// </summary>
/// <param name="ca"></param>
public void SetClientLost(ClientAliveInfo ca)
{
SetClientState(ca, ClientOnlineState.Lost);
}
/// <summary>
/// 服务端检活
/// </summary>
public void CheckClientState()
{
foreach (var client in _clients)
{
if ((DateTime.Now - client.BeatTime).TotalSeconds > _timeoutOffline)
{
SetClientState(client, ClientOnlineState.Offline);
}
}
}
/// <summary>
/// 保存终端信息
/// </summary>
/// <param name="ca"></param>
public ClientAliveInfo UpsertClient(ClientAliveInfo ca)
{
var client = _clients.Find(x => x.DeviceName.Equals(ca.DeviceName) && x.DeviceId.Equals(ca.DeviceId));
if (client != null)
{
client.AppVersion = ca.AppVersion;
client.UserName = ca.UserName;
SetUserName(ref client, ca.UserName);
SetClientLifeState(ref client, ca.State);
}
else
{
ca.OnTime = DateTime.Now;
_clients.Add(ca);
client = ca;
//终端加入事件
if (OnClientJoin != null)
{
OnClientJoin.BeginInvoke(this, ca, null, null);
}
}
client.BeatCount++;
//统一设置跳动时间
client.BeatTime = DateTime.Now;
if (client.State == ClientLifeState.Byebye)
{
client.LeaveTime = DateTime.Now;
SetClientState(client, ClientOnlineState.Offline);
}
else
{
SetClientState(client, ClientOnlineState.On);
}
return client;
}
/// <summary>
/// 移除指定终端
/// </summary>
/// <param name="deviceName"></param>
/// <param name="deviceId"></param>
public void Remove(string deviceName, string deviceId)
{
_clients.RemoveAll(x => x.DeviceName == deviceName && x.DeviceId == deviceId);
}
/// <summary>
/// 数据接收完成回调
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void _socket_AfterReceiveEnd(object sender, DataTransferArgs args)
protected override void _socket_AfterReceiveEnd(object sender, DataTransferArgs args)
{
try
{
GC.Collect();
HeartBeatPackage pg = HeartBeatPackage.Parse(args.Data);
HeartBeatPublishPackage pg = HeartBeatPublishPackage.Parse(args.Data);
HeartBeatPackage hbp = pg.HeartBeat;
ClientAliveInfo ca = new ClientAliveInfo()
{
DeviceName = pg.DeviceName,
DeviceId = pg.DeviceId,
AppVersion = pg.AppVersion,
UserName = pg.UserName,
State = (ClientLifeState)Enum.Parse(typeof(ClientLifeState), pg.StateName.ToString())
DeviceName = hbp.DeviceName,
DeviceId = hbp.DeviceId,
AppVersion = hbp.AppVersion,
UserName = hbp.UserName,
State = (ClientLifeState)Enum.Parse(typeof(ClientLifeState), hbp.StateName.ToString())
};
var client = UpsertClient(ca);
if (OnClientMessageReceive != null)
{
OnClientMessageReceive.BeginInvoke(this, client, args.IP, args.Port, null, null);
OnClientMessageReceive.BeginInvoke(this, client, pg.SrcHost, pg.SrcPort, null, null);
}
}
catch (Exception ex)
{
var ex2 = ex;
Console.WriteLine(ex.Message);
}
}
}
......
......@@ -2,7 +2,7 @@
## 项目介绍
Mozi.StateService是一个心跳服务组件,基于UDP开发。项目主要面向终端检活场景,可用组件:
Mozi.StateService是一个.Net心跳服务组件,基于UDP Socket开发。项目主要面向终端检活场景,可用组件:
### HeartBeatService
心跳客户端
......@@ -28,7 +28,7 @@ Mozi.StateService是一个心跳服务组件,基于UDP开发。项目主要面
~~~shell
dotnet add package Mozi.StateService --version 1.2.5
dotnet add package Mozi.StateService --version 1.2.6
~~~
## 使用说明
......
......@@ -74,6 +74,10 @@ Mozi.HttpEmbedded在Socket之上使用异步单线程模型,构建了一个HTTP
dotnet add package Mozi.HttpEmbedded --version 1.2.5
~~~
## 项目依赖
## 功能与版本迭代
不定期对Mozi.HttpEmbedded的功能进行完善,解决各种BUG。HTTP标准功能繁多,需要一步步实现。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册