/* * 该类用于管理tcp作为服务端连接通讯 */ using System; using System.Collections.Generic; using System.Net.Sockets; using System.Threading; using System.Net; using Shared; using HDL_ON.Entity; namespace HDL_ON.DriverLayer { /// /// TCP服务端 /// public class Control_TcpServer { private Socket ServerSocket = null;//服务端 public Dictionary dic_ClientSocket = new Dictionary();//tcp客户端字典 private Dictionary dic_ClientThread = new Dictionary();//线程字典,每新增一个连接就添加一条线程 private bool Flag_Listen = true;//监听客户端连接的标志 /// /// 启动服务 /// /// 端口号 public bool OpenServer(int port = 8586) { 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; } } /// /// 关闭服务 /// 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(); } /// /// 监听客户端请求的方法; /// 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); } } /// /// 接收数据 /// /// 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(arrMsgRec, 0, length); if (!string.IsNullOrEmpty(tcpDataString)) { AnalysisTcpData(socketClient, tcpDataString); } MainPage.Log(tcpDataString); } } catch (Exception ex) { MainPage.Log($"tcpListener error 2 : {ex.Message}"); } Thread.Sleep(100); } } string tcpFunctionOidJsonString = ""; /// /// 获取列表数据回调方法 /// public Action GetListResponseAction; /// /// 处理tcp数据 /// void AnalysisTcpData(Socket socket, string tcpDataString) { MainPage.Log($"tcpDataString: {tcpDataString}"); var obj = Newtonsoft.Json.JsonConvert.DeserializeObject(tcpDataString); if (obj == null) { return; } var tcpCommand = obj.GetValue("command").ToString(); var tcpType = obj.GetValue("type").ToString(); switch (tcpCommand) { //获取数据返回 case "get_list_response": GetListResponseAction?.Invoke(tcpDataString); break; /* case "search":// 适用于搜索 case "read":// 用于依次读取相关类型信息状态 case "set_list":// 修改列表 case "write":// 用于依次控制相关类型信息 case "delete":// 用于删除相关操作 case "initialize":// 初始化 case "find":// 设备定位 case "get":// 用于获取sid当前状态 case "set":// 用于控制sid相关参数 */ case "add":// 用于增加功能 switch (tcpType) { case "device_oid":// 用于原生态设备读写相关操作 tcpFunctionOidJsonString = tcpDataString; break; case "device_sid": var addSidFunction = Newtonsoft.Json.JsonConvert.DeserializeObject(tcpDataString); Application.RunOnMainThread(() => { var tipDialog = new UI.UpdataTcpResidenceDataDialog(); var tcpLocalFunction = Newtonsoft.Json.JsonConvert.DeserializeObject>(Newtonsoft.Json.JsonConvert.SerializeObject(addSidFunction.objects)); tipDialog.ShowDialog(tcpLocalFunction, tcpFunctionOidJsonString); }); break; } break; case "get_list"://获取列表 switch (tcpType) { /* case "space":// 适用于全部设备, 获取空间信息 case "device":// 网关或者其他A设备 case "device_mac":// 用于设备机身号码相关操作 case "scene":// 用于场景功能读写 case "security":// 用于安防功能读写 case "remote":// 用于远程信息读写操作 case "logic":// 用于逻辑自动化读写操作 case "global":// 用于组播搜索A设备 */ case "device_oid":// 用于原生态设备读写相关操作 var bytes = FileUtils.ReadFile("AProtocolData_FunctionOid"); //var jsonString = System.Text.Encoding.UTF8.GetString(bytes); //if (!string.IsNullOrEmpty(jsonString)) if (bytes.Length > 0) { socket.Send(bytes); MainPage.Log($"send oid list to 8586 prot :{ System.Text.Encoding.UTF8.GetString(bytes)}"); } break; case "device_sid":// 用于功能模型读写操作 var sendSidObj = new TcpTransmissionObject(); sendSidObj.from_oid = ""; sendSidObj.to_oid = ""; sendSidObj.time_stamp = ""; sendSidObj.type = "device_sid"; sendSidObj.command = "get_list_response"; //转换成bus需要的数据格式 var localFunction = DB_ResidenceData.functionList.GetAllFunction(); var localFunctionString = Newtonsoft.Json.JsonConvert.SerializeObject(localFunction); var tcpFunction = Newtonsoft.Json.JsonConvert.DeserializeObject>(localFunctionString); sendSidObj.objects.AddRange(tcpFunction); var sendSidJson = Newtonsoft.Json.JsonConvert.SerializeObject(sendSidObj); var sendSidBytes = System.Text.Encoding.UTF8.GetBytes(sendSidJson); socket.Send(sendSidBytes, sendSidBytes.Length, SocketFlags.OutOfBand); MainPage.Log($"send sid list to 8586 prot :{sendSidJson}"); break; } break; } } /// /// 发送数据给指定的客户端 /// /// 客户端套接字 /// 发送的数组 /// 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; } } } /// /// 会话端 /// public class MySession { public Socket TcpSocket;//socket对象 public List m_Buffer = new List();//数据缓存区 public MySession() { } /// /// 发送数据 /// /// public void Send(byte[] buf) { if (buf != null) { TcpSocket.Send(buf); } } /// /// 获取连接的ip /// /// public string GetIp() { IPEndPoint clientipe = (IPEndPoint)TcpSocket.RemoteEndPoint; string _ip = clientipe.Address.ToString(); return _ip; } /// /// 关闭连接 /// public void Close() { TcpSocket.Shutdown(SocketShutdown.Both); } /// /// 提取正确数据包 /// 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; } /// /// 添加队列数据 /// /// public void AddQueue(byte[] buffer) { m_Buffer.AddRange(buffer); } /// /// 清除缓存 /// public void ClearQueue() { m_Buffer.Clear(); } } /// /// bus软件传输功能的对象 /// public class TcpTransmissionObject { public List objects = new List(); public string from_oid = ""; public string to_oid = ""; public string time_stamp = ""; public string type = ""; public string command = ""; } /// /// bus软件传输的功能对象 /// 仅在与bus软件传递数据时使用, /// Function对象包含了该对象的所有内容, /// 此对象为了减少传输数据使用 /// public class TcpObject { public string sid = "";// "0301011234567801012301230123"; /// /// A协议功能的特性 /// 如:是AC功能:特性:on_off,mode,fan,temperature /// attri /// public List function = new List(); /// /// 备注 /// public string name; } }