From b752082a223330544280dcc560785ecefbd6b60f Mon Sep 17 00:00:00 2001 From: zhangfl0220 Date: Wed, 13 Dec 2017 18:01:19 +0800 Subject: [PATCH] =?UTF-8?q?DAServer.CS=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SCADA/Program/BatchCoreService/DAService.cs | 44 ++++++++++++++------- SCADA/Program/BatchCoreTest/Program.cs | 2 +- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/SCADA/Program/BatchCoreService/DAService.cs b/SCADA/Program/BatchCoreService/DAService.cs index ccca4af..c24b398 100644 --- a/SCADA/Program/BatchCoreService/DAService.cs +++ b/SCADA/Program/BatchCoreService/DAService.cs @@ -212,9 +212,13 @@ namespace BatchCoreService } } + #region 初始化服务器,连接和主机等 + public DAService() { - if (!EventLog.SourceExists(SERVICELOGSOURCE)) + + #region 创建事件日志 + if (!EventLog.SourceExists(SERVICELOGSOURCE))//服务器记录的源和名称都是"DataProcess" { EventLog.CreateEventSource(SERVICELOGSOURCE, SERVICELOGNAME); } @@ -228,6 +232,8 @@ namespace BatchCoreService // 當EventLog 滿了就把最早的那一筆log 蓋掉。 Log.ModifyOverflowPolicy(OverflowAction.OverwriteAsNeeded, 7); } + #endregion + _scales = new List(); _drivers = new SortedList(); _alarmList = new List(ALARMLIMIT + 10); @@ -262,6 +268,8 @@ namespace BatchCoreService } } + #endregion + public void Dispose() { lock (this) @@ -409,7 +417,7 @@ namespace BatchCoreService { foreach (IDriver reader in _drivers.Values) { - reader.OnClose += new ShutdownRequestEventHandler(reader_OnClose); + reader.OnClose += new ShutdownRequestEventHandler(reader_OnClose);//每次连接失败,记录失败原因日志。 if (reader.IsClosed) { //if (reader is IFileDriver) @@ -574,8 +582,8 @@ namespace BatchCoreService * 服务启动时,向整个局域网UDP广播加密的主机名、连接字符串等信息 */ //socketThreadList = new Dictionary(); - tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - IPEndPoint LocalPort = new IPEndPoint(IPAddress.Any, PORT); + tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//新建一个套接字 + IPEndPoint LocalPort = new IPEndPoint(IPAddress.Any, PORT);//IPEndPoint是IP和端口对的组合,IPAdress.Any使用你机器上一个可用的IP来初始化这个IP地址对象。 tcpServer.Bind(LocalPort); tcpServer.Listen(100); ThreadPool.QueueUserWorkItem(new WaitCallback(AcceptWorkThread)); @@ -607,7 +615,7 @@ namespace BatchCoreService if (reader.MoveToAttribute("TestCycle")) int.TryParse(reader.Value, out CYCLE); if (reader.MoveToAttribute("SendTimeout")) - int.TryParse(reader.Value, out SENDTIMEOUT); + int.TryParse(reader.Value, out SENDTIMEOUT);//客户端Socket通讯发送超时 } break; case "Hda"://历史记录的参数 @@ -652,37 +660,37 @@ namespace BatchCoreService while (true) { //if (tcpServer.Poll(0, SelectMode.SelectRead)) - Socket s_Accept = tcpServer.Accept(); + Socket s_Accept = tcpServer.Accept();//有连接后,接受客户端的连接请求。 //IPAddress addr = (s_Accept.RemoteEndPoint as IPEndPoint).Address; s_Accept.SendTimeout = SENDTIMEOUT; - IPAddress addr = (s_Accept.RemoteEndPoint as IPEndPoint).Address; + IPAddress addr = (s_Accept.RemoteEndPoint as IPEndPoint).Address;//客户端的IP地址 try { - if (!_socketThreadList.ContainsKey(addr)) + if (!_socketThreadList.ContainsKey(addr))//键查找:如果字典中不存在IP地址,将客户端的IP添加到字典中 _socketThreadList.Add(addr, s_Accept); } catch (Exception err) { AddErrorLog(err); } - ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(ReceiveWorkThread), s_Accept); + ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(ReceiveWorkThread), s_Accept);//线程池中不安全的线程。线程池将s_Accept传送给ReceiveWorkThread } } void ReceiveWorkThread(object obj) { - Socket s_Receive = (Socket)obj; + Socket s_Receive = (Socket)obj;//创建新的接收通道Socket IPAddress addr = null; try { - addr = (s_Receive.RemoteEndPoint as IPEndPoint).Address; + addr = (s_Receive.RemoteEndPoint as IPEndPoint).Address;//获取远程终结点。 } catch (Exception err) { AddErrorLog(err); return; } - byte[] buffer = new byte[s_Receive.ReceiveBufferSize]; // 创建接收缓冲 + byte[] buffer = new byte[s_Receive.ReceiveBufferSize]; // 创建接收缓冲,默认的接收缓冲区的大小是多少? while (true) { try @@ -698,12 +706,12 @@ namespace BatchCoreService { //buffer[0]是协议头,1是指令号,2是读方式(缓存还是设备),3、4是ID,5是长度,后接变量值 byte command = buffer[1]; - switch (command) + switch (command)//根据指令号来操作对应的程序。 { - case FCTCOMMAND.fctReadSingle: + case FCTCOMMAND.fctReadSingle://来自DataServer中的IServer下面的类FCTCOMMAND { //DataSource source = buffer[2] == 0 ? DataSource.Cache : DataSource.Device; - short id = BitConverter.ToInt16(buffer, 3); + short id = BitConverter.ToInt16(buffer, 3);//将二进制数转换成整数 byte length = buffer[5]; byte[] send = new byte[5 + length]; for (int i = 0; i < 5; i++) @@ -1347,6 +1355,8 @@ namespace BatchCoreService return rs; } + #region New region + void grp_DataChange(object sender, DataChangeEventArgs e) { var data = e.Values; @@ -1376,7 +1386,11 @@ namespace BatchCoreService ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(this.SendData), new TempCachedData(addr, data)); } } + + #endregion + //此处发生内存泄漏;需要试验CLRProfile确定泄漏原因;改回原方法测试;看是否解决队列堵塞问题。对于客户端Grp,要过滤掉 + private void SendData(object obj) { var tempdata = obj as TempCachedData; diff --git a/SCADA/Program/BatchCoreTest/Program.cs b/SCADA/Program/BatchCoreTest/Program.cs index 55e9ef3..582c871 100644 --- a/SCADA/Program/BatchCoreTest/Program.cs +++ b/SCADA/Program/BatchCoreTest/Program.cs @@ -30,7 +30,7 @@ namespace BatchCoreService // Create a ServiceHost for the CalculatorService type and // provide the base address. - serviceHost = new ServiceHost(typeof(DAService)); + serviceHost = new ServiceHost(typeof(DAService));//MCF通讯 // Open the ServiceHostBase to create listeners and start // listening for messages.