/// <summary>
        /// Process data received by UDP.
        /// </summary>
        protected void UdpReceiveCallback(IAsyncResult ar)
        {
            byte[] buf = null;

            if (!terminated)
            {
                try
                {
                    IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
                    buf = slaveConn.UdpClient.EndReceive(ar, ref remoteEP);
                    slaveConn.RemoteAddress = remoteEP.Address.ToString();
                    slaveConn.RemotePort    = remoteEP.Port;

                    Log.WriteLine();
                    Log.WriteAction(Locale.IsRussian ?
                                    "Получены данные от {0}:{1}" :
                                    "Data received from {0}:{1}",
                                    slaveConn.RemoteAddress, slaveConn.RemotePort);

                    if (buf == null)
                    {
                        Log.WriteAction(Locale.IsRussian ?
                                        "Данные пусты" :
                                        "Data is empty");
                    }
                }
                catch (Exception ex)
                {
                    Log.WriteException(ex, Locale.IsRussian ?
                                       "Ошибка при приёме данных" :
                                       "Error receiving data");
                }
            }

            if (buf != null)
            {
                if (options.DeviceMapping == DeviceMapping.ByIPAddress)
                {
                    if (deviceDict.GetDeviceGroup(slaveConn.RemoteAddress,
                                                  out DeviceDictionary.DeviceGroup deviceGroup))
                    {
                        lock (deviceLock)
                        {
                            // process the incoming request for the devices with the specified IP address
                            ProcessIncomingRequest(deviceGroup, buf, 0, buf.Length, requestArgs);
                        }
                    }
                    else
                    {
                        Log.WriteError(CommPhrases.UnableFindDevice, slaveConn.RemoteAddress);
                    }
                }
                else if (options.DeviceMapping == DeviceMapping.ByDriver)
                {
                    lock (deviceLock)
                    {
                        // process the incoming request for any device
                        ProcessIncomingRequest(LineContext.SelectDevices(), buf, 0, buf.Length, requestArgs);
                    }
                }
            }

            if (!terminated)
            {
                slaveConn.BeginReceive(UdpReceiveCallback);
            }
        }
示例#2
0
        /// <summary>
        /// Communication cycle running in a separate thread.
        /// </summary>
        protected void Execute()
        {
            int      threadDelay    = options.Behavior == ChannelBehavior.Slave ? SlaveThreadDelay : ScadaUtils.ThreadDelay;
            TimeSpan clientLifetime = TimeSpan.FromSeconds(options.ClientLifetime);

            while (!terminated)
            {
                TcpConnection conn = null;

                try
                {
                    // open incoming connections
                    while (tcpListener.Pending() && !terminated)
                    {
                        Log.WriteAction(Locale.IsRussian ?
                                        "Соединение с клиентом {0}" :
                                        "Connect to the client {0}", conn.RemoteAddress);
                        conn = new TcpConnection(Log, tcpListener.AcceptTcpClient());

                        if (options.ConnectionMode == ConnectionMode.Shared)
                        {
                            BindDevices(conn, LineContext.SelectDevices());
                        }
                        else if (options.DeviceMapping == DeviceMapping.ByIPAddress)
                        {
                            if (deviceDict.GetDeviceGroup(conn.RemoteAddress,
                                                          out DeviceDictionary.DeviceGroup deviceGroup))
                            {
                                BindDevices(conn, deviceGroup);
                            }
                            else
                            {
                                Log.WriteError(CommPhrases.UnableFindDevice, conn.RemoteAddress);
                                conn.CloseMark = true;
                            }
                        }

                        lock (connList)
                        {
                            connList.Add(conn);
                        }
                    }

                    // receive data from connected clients
                    DateTime utcNow  = DateTime.UtcNow;
                    int      connIdx = 0;

                    while (connIdx < connList.Count && !terminated)
                    {
                        conn = connList[connIdx];

                        lock (conn)
                        {
                            // receive available data
                            if (conn.TcpClient.Available > 0 && !conn.CloseMark)
                            {
                                ReceiveData(conn);
                            }

                            // close inactive connection
                            if (utcNow - conn.ActivityTime > clientLifetime || conn.CloseMark)
                            {
                                Log.WriteAction(Locale.IsRussian ?
                                                "Отключение клиента {0}" :
                                                "Disconnect the client {0}", conn.RemoteAddress);
                                conn.Close();

                                lock (connList)
                                {
                                    connList.RemoveAt(connIdx);
                                }
                            }
                            else
                            {
                                connIdx++;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (conn == null)
                    {
                        Log.WriteException(ex, Locale.IsRussian ?
                                           "Ошибка при взаимодействии с клиентами" :
                                           "Error communicating with clients");
                    }
                    else
                    {
                        Log.WriteException(ex, Locale.IsRussian ?
                                           "Ошибка при взаимодействии с клиентом {0}" :
                                           "Error communicating with the client {0}", conn.RemoteAddress);
                    }
                }
                finally
                {
                    Thread.Sleep(threadDelay);
                }
            }
        }