/*
|
* 该类用于管理tcp连接通讯
|
*/
|
using System;
|
using System.Collections.Generic;
|
using System.Net.Sockets;
|
using System.Threading;
|
using System.Net;
|
|
namespace HDL_ON.DAL.Net
|
{
|
/// <summary>
|
/// 服务端
|
/// </summary>
|
public class TcpListener
|
{
|
|
private Socket ServerSocket = null;//服务端
|
public Dictionary<string, MySession> dic_ClientSocket = new Dictionary<string, MySession>();//tcp客户端字典
|
private Dictionary<string, Thread> dic_ClientThread = new Dictionary<string, Thread>();//线程字典,每新增一个连接就添加一条线程
|
private bool Flag_Listen = true;//监听客户端连接的标志
|
|
/// <summary>
|
/// 启动服务
|
/// </summary>
|
/// <param name="port">端口号</param>
|
public bool OpenServer(int port)
|
{
|
try
|
{
|
Flag_Listen = true;
|
// 创建负责监听的套接字,注意其中的参数;
|
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
// 创建包含ip和端口号的网络节点对象;
|
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port);
|
try
|
{
|
// 将负责监听的套接字绑定到唯一的ip和端口上;
|
ServerSocket.Bind(endPoint);
|
}
|
catch
|
{
|
return false;
|
}
|
// 设置监听队列的长度;
|
ServerSocket.Listen(100);
|
// 创建负责监听的线程;
|
Thread Thread_ServerListen = new Thread(ListenConnecting);
|
Thread_ServerListen.IsBackground = true;
|
Thread_ServerListen.Start();
|
|
MainPage.Log("启动tcp侦听");
|
return true;
|
}
|
catch
|
{
|
return false;
|
}
|
}
|
/// <summary>
|
/// 关闭服务
|
/// </summary>
|
public void CloseServer()
|
{
|
lock (dic_ClientSocket)
|
{
|
foreach (var item in dic_ClientSocket)
|
{
|
item.Value.Close();//关闭每一个连接
|
}
|
dic_ClientSocket.Clear();//清除字典
|
}
|
lock (dic_ClientThread)
|
{
|
foreach (var item in dic_ClientThread)
|
{
|
item.Value.Abort();//停止线程
|
}
|
dic_ClientThread.Clear();
|
}
|
Flag_Listen = false;
|
//ServerSocket.Shutdown(SocketShutdown.Both);//服务端不能主动关闭连接,需要把监听到的连接逐个关闭
|
if (ServerSocket != null)
|
ServerSocket.Close();
|
|
}
|
/// <summary>
|
/// 监听客户端请求的方法;
|
/// </summary>
|
private void ListenConnecting()
|
{
|
while (Flag_Listen) // 持续不断的监听客户端的连接请求;
|
{
|
try
|
{
|
Socket sokConnection = ServerSocket.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字;
|
// 将与客户端连接的 套接字 对象添加到集合中;
|
string str_EndPoint = sokConnection.RemoteEndPoint.ToString();
|
MySession myTcpClient = new MySession() { TcpSocket = sokConnection };
|
//创建线程接收数据
|
Thread th_ReceiveData = new Thread(ReceiveData);
|
th_ReceiveData.IsBackground = true;
|
th_ReceiveData.Start(myTcpClient);
|
//把线程及客户连接加入字典
|
dic_ClientThread.Add(str_EndPoint, th_ReceiveData);
|
dic_ClientSocket.Add(str_EndPoint, myTcpClient);
|
}
|
catch
|
{
|
|
}
|
Thread.Sleep(200);
|
}
|
}
|
/// <summary>
|
/// 接收数据
|
/// </summary>
|
/// <param name="sokConnectionparn"></param>
|
private void ReceiveData(object sokConnectionparn)
|
{
|
MySession tcpClient = sokConnectionparn as MySession;
|
Socket socketClient = tcpClient.TcpSocket;
|
bool Flag_Receive = true;
|
|
while (Flag_Receive)
|
{
|
try
|
{
|
// 定义一个2M的缓存区;
|
byte[] arrMsgRec = new byte[1024 * 1024 * 2];
|
// 将接受到的数据存入到输入 arrMsgRec中;
|
int length = -1;
|
try
|
{
|
length = socketClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度;
|
}
|
catch (Exception ex)
|
{
|
MainPage.Log($"tcpListener error 1 : {ex.Message}");
|
|
Flag_Receive = false;
|
// 从通信线程集合中删除被中断连接的通信线程对象;
|
string keystr = socketClient.RemoteEndPoint.ToString();
|
dic_ClientSocket.Remove(keystr);//删除客户端字典中该socket
|
dic_ClientThread[keystr].Abort();//关闭线程
|
dic_ClientThread.Remove(keystr);//删除字典中该线程
|
|
tcpClient = null;
|
socketClient = null;
|
break;
|
}
|
byte[] buf = new byte[length];
|
Array.Copy(arrMsgRec, buf, length);
|
lock (tcpClient.m_Buffer)
|
{
|
//tcpClient.m_Buffer.Add(buf);
|
var tcpDataString = System.Text.Encoding.UTF8.GetString(buf);
|
AnalysisTcpData(tcpDataString);
|
MainPage.Log(tcpDataString);
|
}
|
}
|
catch (Exception ex)
|
{
|
MainPage.Log($"tcpListener error 2 : {ex.Message}");
|
}
|
Thread.Sleep(100);
|
}
|
}
|
List<Entity.FunctionOid> tcpAddFunctionOidObjects = new List<Entity.FunctionOid>();
|
/// <summary>
|
/// 处理tcp数据
|
/// </summary>
|
void AnalysisTcpData(string tcpDataString)
|
{
|
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(tcpDataString);
|
if(obj == null)
|
{
|
return;
|
}
|
var tcpCommand = obj.GetValue("command").ToString();
|
var tcpType = obj.GetValue("type").ToString();
|
|
switch (tcpCommand)
|
{
|
/*
|
case "search":// 适用于搜索
|
case "get_list"://获取列表
|
case "set_list":// 修改列表
|
case "write":// 用于依次控制相关类型信息
|
case "delete":// 用于删除相关操作
|
case "initialize":// 初始化
|
case "find":// 设备定位
|
case "get":// 用于获取sid当前状态
|
case "set":// 用于控制sid相关参数
|
*/
|
case "add":// 用于增加功能
|
switch (tcpType)
|
{
|
case "device_oid":// 用于原生态设备读写相关操作
|
tcpAddFunctionOidObjects = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Entity.FunctionOid>>(obj.GetValue("objects").ToString());
|
|
break;
|
case "device_sid":
|
var addSidFunction = Newtonsoft.Json.JsonConvert.DeserializeObject<TcpAddFunctionSidObject>(tcpDataString);
|
Shared.Application.RunOnMainThread(() => {
|
var tipDialog = new HDL_ON.UI.UpdataTcpResidenceDataDialog();
|
tipDialog.ShowDialog(addSidFunction.objects, tcpAddFunctionOidObjects);
|
});
|
break;
|
}
|
break;
|
case "read":// 用于依次读取相关类型信息状态
|
switch (tcpType)
|
{
|
/*
|
case "space":// 适用于全部设备, 获取空间信息
|
case "device":// 网关或者其他A设备
|
case "device_mac":// 用于设备机身号码相关操作
|
case "scene":// 用于场景功能读写
|
case "security":// 用于安防功能读写
|
case "remote":// 用于远程信息读写操作
|
case "logic":// 用于逻辑自动化读写操作
|
case "global":// 用于组播搜索A设备
|
*/
|
case "device_oid":// 用于原生态设备读写相关操作
|
Dictionary<string, object> dic_oid = new Dictionary<string, object>();
|
dic_oid.Add("from_oid", null);
|
dic_oid.Add("to_oid", null);
|
dic_oid.Add("time_stamp", null);
|
dic_oid.Add("type", "device_oid");
|
dic_oid.Add("command", "get_list_response");
|
|
List<object> oidObjList = new List<object>();
|
foreach (var d01 in Entity.DB_ResidenceData.residenceData.functionList.GetAllDeviceFunctionList())
|
{
|
Dictionary<string, object> d0 = new Dictionary<string, object>();
|
d0.Add("oid", d01.sid);
|
d0.Add("status", "online");
|
d0.Add("device_name", d01.name);
|
d0.Add("device_model","HDL MD0602.523");
|
d0.Add("device_mac", "123456789067890");
|
d0.Add("hw_info", "STM32F104");
|
d0.Add("fw_version","HDL_V04.01U");
|
oidObjList.Add(d0);
|
}
|
dic_oid.Add("objects", oidObjList);
|
Newtonsoft.Json.JsonConvert.SerializeObject(dic_oid);
|
break;
|
case "device_sid":// 用于功能模型读写操作
|
Dictionary<string, object> dic_sid = new Dictionary<string, object>();
|
dic_sid.Add("from_oid", null);
|
dic_sid.Add("to_oid", null);
|
dic_sid.Add("time_stamp", null);
|
dic_sid.Add("type", "device_sid");
|
dic_sid.Add("command", "get_list_response");
|
|
List<object> sidObjList = new List<object>();
|
foreach (var d01 in Entity.DB_ResidenceData.residenceData.functionList.GetAllDeviceFunctionList())
|
{
|
Dictionary<string, object> d0 = new Dictionary<string, object>();
|
d0.Add("sid", d01.sid);
|
d0.Add("name", d01.name);
|
d0.Add("type", d01.functionType);
|
sidObjList.Add(d0);
|
}
|
dic_sid.Add("objects", sidObjList);
|
Newtonsoft.Json.JsonConvert.SerializeObject(dic_sid);
|
break;
|
}
|
break;
|
}
|
}
|
|
|
/// <summary>
|
/// 发送数据给指定的客户端
|
/// </summary>
|
/// <param name="_endPoint">客户端套接字</param>
|
/// <param name="_buf">发送的数组</param>
|
/// <returns></returns>
|
public bool SendData(string _endPoint, byte[] _buf)
|
{
|
MySession myT = new MySession();
|
if (dic_ClientSocket.TryGetValue(_endPoint, out myT))
|
{
|
myT.Send(_buf);
|
return true;
|
}
|
else
|
{
|
return false;
|
}
|
}
|
}
|
|
/// <summary>
|
/// 会话端
|
/// </summary>
|
public class MySession
|
{
|
public Socket TcpSocket;//socket对象
|
public List<byte> m_Buffer = new List<byte>();//数据缓存区
|
|
public MySession()
|
{
|
|
}
|
|
/// <summary>
|
/// 发送数据
|
/// </summary>
|
/// <param name="buf"></param>
|
public void Send(byte[] buf)
|
{
|
if (buf != null)
|
{
|
TcpSocket.Send(buf);
|
}
|
}
|
/// <summary>
|
/// 获取连接的ip
|
/// </summary>
|
/// <returns></returns>
|
public string GetIp()
|
{
|
IPEndPoint clientipe = (IPEndPoint)TcpSocket.RemoteEndPoint;
|
string _ip = clientipe.Address.ToString();
|
return _ip;
|
}
|
/// <summary>
|
/// 关闭连接
|
/// </summary>
|
public void Close()
|
{
|
TcpSocket.Shutdown(SocketShutdown.Both);
|
}
|
/// <summary>
|
/// 提取正确数据包
|
/// </summary>
|
public byte[] GetBuffer(int startIndex, int size)
|
{
|
byte[] buf = new byte[size];
|
m_Buffer.CopyTo(startIndex, buf, 0, size);
|
m_Buffer.RemoveRange(0, startIndex + size);
|
return buf;
|
}
|
|
/// <summary>
|
/// 添加队列数据
|
/// </summary>
|
/// <param name="buffer"></param>
|
public void AddQueue(byte[] buffer)
|
{
|
m_Buffer.AddRange(buffer);
|
}
|
/// <summary>
|
/// 清除缓存
|
/// </summary>
|
public void ClearQueue()
|
{
|
m_Buffer.Clear();
|
}
|
}
|
|
|
public class TcpAddFunctionSidObject
|
{
|
public List<Entity.Function> objects;
|
|
public string type;//device_sid
|
public string from_oid;//": null,
|
public string to_oid;//": null,
|
public string time_stamp;//": null,
|
public string command;//": "add"
|
}
|
|
//public class SidObject
|
//{
|
// public List<Entity.Trait> function = new List<Entity.Trait>();
|
// public string sid;//": "000101E10FEB7212040100010700",
|
// public string name;//": "HVAC-1"
|
//}
|
|
}
|