示例#1
0
        private void CommunicationLoop()
        {
            logger.Verb("CommunicationLoop BEGIN");

            try
            {
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.ReceiveTimeout = 10000;
                socket.SendTimeout    = 10000;

                logger.Verb($"socket.ConnectAsync(...) {Host} {Port}");

                var connectionTask = socket.ConnectAsync(Host, Port);

                Task.WaitAny(new[] { connectionTask }, 10000);

                if (!IsSocketConnected())
                {
                    throw new Exception("Connection error");
                }

                if (state == ClientState.Connecting)
                {
                    state = ClientState.Connected;
                }

                StateChanged?.Invoke();

                while (true)
                {
                    bool socketConnected = IsSocketConnected();
                    if (!(socketConnected && state == ClientState.Connected))
                    {
                        logger.Debug("Connection break " + socketConnected + " " + state);
                        break;
                    }

                    int available = socket.Available;
                    if (available > 0)
                    {
                        IEnumerable <byte[]> dataLines = null;

                        CPSocketHandler socketHanlder = new CPSocketHandler();

                        Exception exception = null;
                        try
                        {
                            bool bufferProcessed = false;
                            do
                            {
                                byte[] recBuffer = new byte[1024];

                                int bytesRec = socket.Receive(recBuffer);

                                if (bytesRec > 0)
                                { //The ControlPoint protocol is text-based. Each command line terminates
                                  //with CR/LF.Tokens are space separated. All identifiers are case-sensitive.

                                    dataLines = socketHanlder.ReadLines(recBuffer, bytesRec);

                                    bufferProcessed = (dataLines != null);
                                }
                                else
                                {// socket closed...
                                    socketConnected = false;
                                    break;
                                }
                            }while (!bufferProcessed);
                        }
                        catch (Exception ex)
                        {
                            logger.Error(ex);
                            exception = ex;
                        }

                        if (dataLines != null)
                        {
                            foreach (var bytes in dataLines)
                            {
                                var cpResponse   = CPResponseBase.Create(bytes);
                                var responseType = cpResponse?.ResponseType ?? CPResponseType.Unknown;

                                if (responseType == CPResponseType.Response || cpResponse.ResponseType == CPResponseType.Galileo)
                                {
                                    ProcessResponse(cpResponse, exception);
                                }
                                else if (cpResponse.ResponseType == CPResponseType.Notify)
                                {
                                    ProcessNotification(cpResponse);
                                }
                                else
                                {
                                    ProcessResponse(null, exception);
                                }
                            }

                            dataLines = null;
                        }
                    }

                    socketConnected = IsSocketConnected();
                    if (!(socketConnected && state == ClientState.Connected))
                    {
                        logger.Debug("Connection break " + socketConnected + " " + state);
                        break;
                    }

                    {                            // Response must be received before the next Request is sent!
                        if (sendCommand == null) // обнуляется при получении ответа
                        {
                            if (TryGetCommand(out var command))
                            {
                                try
                                {
                                    var seq     = command.seq;
                                    var request = (CPRequest)command.request;

                                    byte[] sendBuffer = request.GetBytes();
                                    int    bytesSent  = socket.Send(sendBuffer);

                                    sendCommand = command;

                                    logger.Debug(">> " + sendCommand.ToString() + "bytesSent: " + bytesSent);
                                }
                                catch (Exception ex)
                                {
                                    logger.Error(ex);

                                    ProcessResponse(null, ex);
                                }
                            }
                        }
                    }

                    syncEvent.WaitOne(10);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex);
            }
            finally
            {
                if (socket != null)
                {
                    if (socket.Connected)
                    {
                        socket.Shutdown(SocketShutdown.Both);
                    }

                    socket.Close();
                    socket = null;
                }

                DrainCommands();

                isAuthenticated = false;
                state           = ClientState.Disconnected;
                StateChanged?.Invoke();
            }

            logger.Verb("CommunicationLoop END");
        }