Пример #1
0
        private bool ParseOptions(Packet.Packet packet)
        {
            switch (packet.Header.Option1)
               {
               case PacketOption1.Acknowledge:
                   {
                       var acknowledge = StructConvertor.FromBytes<Acknowledge>(packet.Data.Content);
                       // Обработка пакета подверждения доставки сообщения
                       // Если первый бит опций равен ACK и CRC в пакете совпала с последним отправленым пакетом для этого клиента
                      // if (_clientArray[packet.Header.Sender].LastMessageCrc == BitConverter.ToUInt16(packet.ByteData, 0))
                       if (_clientArray[packet.Header.Sender].LastMessageCrc == acknowledge.DeliveredPacketCrc)
                       {
                           // Елси был доставлен пакет "запрос на передачу файла" то запустить таймер ожидания ответа
                           if (_clientArray[packet.Header.Sender].LastPacket.Data.Type == DataType.FileRequest)
                           {
                               OnMessageRecived(new MessageRecivedEventArgs(MessageType.WaitFileRecipientAnswer, FileToTransfer.Name, packet.Header.Sender, packet.Header.Recipient));
                               _waitFileTransferAnswerTimer.Change(_waitFileTransferAnswerTimeOut, Timeout.Infinite);
                           }

                           //  Если последний пакет данных успешно доставлен то увеличить количество переданных байт на величину пакета
                           if (_clientArray[packet.Header.Sender].LastPacket.Data.Type == DataType.FileData)
                           {
                               ProcessedFileSize += _filePacketSize;
                           }

                           // Установить что последнее сообщение было доставлено
                           _clientArray[packet.Header.Sender].AnswerEvent.Set();
                           return true;
                       }
                   }
                   break;

               case PacketOption1.FileTransferAllowed:
                   {
                       // Обработка пакета разрешения на передачу файла
                       // Если получено разрешение на передачу файлов и отправитель пакета является тем кому был отправлен запрос на передачу
                       if (Client.AllowSendingFile && Client.FileRecipient == packet.Header.Sender)
                       {
                           // Событие о разрещении на передачу файла
                           OnMessageRecived(new MessageRecivedEventArgs(MessageType.FileTransferAllowed, FileToTransfer.Name, packet.Header.Sender, packet.Header.Recipient));

                           // Начать отправку файла
                           // Отчищает очередь пакетов файла на передачу
                           // TO DO: Добавить отчистку очереди?

                           // Запрещает отправлять файла на последующие запросы до завершения передачи
                           Client.AllowSendingFile = false;
                           // Устанавливает что идет передача файла
                           Client.IsSendingFile = true;
                           // Обнуляет счетчик пакетов
                           Client.CountOfFilePackets = 0;
                           // Запускает поток для упаковки файла в пакеты и добавления их в очередь
                           _fileSenderThread = new Thread(FileSender);
                           _fileSenderThread.Start(packet.Header.Sender);
                       }
                       // Выслать подверждение получения пакета
                       SendAcknowledge(packet);
                       return true;
                   }
                   break;

               case PacketOption1.FileTransferDenied:
                   {
                       // Если получен пакет отмены передачи файла
                       // Если файл принимался
                       if (IsRecivingFile)
                       {
                           // Событие отмены перадачи файла отправителем
                           OnMessageRecived(new MessageRecivedEventArgs(MessageType.FileTransferCanceledBySender, _receivingFileName, packet.Header.Sender, packet.Header.Recipient));

                           CancelRecivingFile();
                           // Выслать подверждение получения пакета
                           SendAcknowledge(packet);
                           return true;
                       }
                       // Если файл отправлялся
                       if (Client.IsSendingFile)
                       {
                           // Событие отмены перадачи файла получателем
                           OnMessageRecived(new MessageRecivedEventArgs(MessageType.FileTransferCanceledByRecipient, FileToTransfer.Name, packet.Header.Sender, packet.Header.Recipient));
                           CancelSendingFile();
                           // Выслать подверждение получения пакета
                           SendAcknowledge(packet);
                           return true;
                       }
                       // Если был отправлен только запрос на передачу файла
                       if (Client.AllowSendingFile)
                       {
                           Client.AllowSendingFile = false;
                           // Событие отказа от приема файла
                           OnMessageRecived(new MessageRecivedEventArgs(MessageType.FileTransferDenied, FileToTransfer.Name, packet.Header.Sender, packet.Header.Recipient));
                       }

                       if (_waitFileTransferAnswer)
                       {
                           _waitFileTransferAnswer = false;
                           // Отправитель отменил запрос
                           OnMessageRecived(new MessageRecivedEventArgs(MessageType.FileRequestCanceledRecipientSide, _receivingFileName, packet.Header.Sender, packet.Header.Recipient));
                       }

                       // Выслать подверждение получения пакета
                       SendAcknowledge(packet);
                       return true;
                   }
                   break;

               case PacketOption1.FileTransferCompleted :
                   {
                       if (packet.Header.Option1 == PacketOption1.FileTransferCompleted)
                       {
                           ProcessedFileSize = 0;
                           Client.IsSendingFile = false;
                           // Событие доставки файла
                           OnMessageRecived(new MessageRecivedEventArgs(MessageType.FileSendingComplete, FileToTransfer.Name, packet.Header.Sender, packet.Header.Recipient));
                           SendAcknowledge(packet);
                           return true;
                       }
                   }
                   break;

               case PacketOption1.InitializationRequest:
                   {
                       SendAcknowledge(packet);

                       if (_clientArray.ContainsKey(packet.Header.Sender))
                       {
                           SendInitializationData(DateTime.UtcNow, _enabledClientIDs, packet.Header.Sender);
                       }
                       return true;
                   }
                   break;
               }
               return false;
        }
Пример #2
0
        // TODO постараться вынести инициализацию в метод Read
        private InitializationData ReadInitialization(SerialPort readport)
        {
            while (true)
               {
               try
               {
                   readport.ReadTo("\xAA\x55");

                   // Считывание данных для создания пакета
                   // Здесь важен строгий порядок считывания байтов, точно как в пакете.
                   byte recipient = (byte)readport.ReadByte();
                   byte sender = (byte)readport.ReadByte();
                   ushort dataLenght = BitConverter.ToUInt16(
                       new byte[] { (byte)readport.ReadByte(), (byte)readport.ReadByte() }, 0);
                   byte option1 = (byte)readport.ReadByte();
                   byte option2 = (byte)readport.ReadByte();
                   ushort crc = BitConverter.ToUInt16(
                       new byte[] { (byte)readport.ReadByte(), (byte)readport.ReadByte() }, 0);

                   // Счетчик количества итерация цикла while
                   int count = 0;
                   while (readport.BytesToRead < dataLenght)
                   {
                       count++;
                       Thread.Sleep(_sleepTime);
                       if (count > dataLenght)
                       {
                           break;
                       }
                   }

                   byte[] data = new byte[dataLenght];
                   readport.Read(data, 0, dataLenght);

                   var packet = new Packet.Packet(new Header(recipient, sender, option1, option2), data);

                       // Проверка crc и id клиента, id отправителя и типа пакета
                       if (packet.Header.Crc == crc && packet.Header.Recipient == ClietnId && packet.Header.Sender == 0 && packet.Data.Type == DataType.Initialization)
                       {
                           SendAcknowledge(packet);

                           var initialization = StructConvertor.FromBytes<InitializationData>(packet.Data.Content);

                           return initialization;
                       }
               }

               catch (InvalidOperationException)
               {
                   IsPortAvailable(readport);
                   Thread.Sleep(3000);
               }

               catch (TimeoutException exception)
               {
                   // TODO ограничить количество отправок запроса
                   SendInitializationRequest();
               }

               catch (Exception exception)
               {
                   LogHelper.GetLogger<CommunicationUnit>().Error("Ошибка при чтение с порта", exception);
               }

               }
        }
Пример #3
0
        private void SendAcknowledge(Packet.Packet packet)
        {
            //  _clientArray[(int)packet.Header.Sender].AddPacketToQueue(BitConverter.GetBytes(Crc16.ComputeChecksum(packet.ByteData)), ClietnId, 0x06, 0x00, true);

            Acknowledge acknowledge = new Acknowledge(Crc16.ComputeChecksum(packet.ByteData));

            _clientArray[(int)packet.Header.Sender].AddPacketToQueue(acknowledge, ClietnId, 0x06, 0x00, true);
        }
Пример #4
0
        private void Read(object readport)
        {
            SerialPort readPort = (SerialPort)readport;

            while (Client.Continue)
            {
                try
                {
                    readPort.ReadTo("\xAA\x55");

                    // Считывание данных для создания пакета
                    // Здесь важен строгий порядок считывания байтов, точно как в пакете.
                    byte recipient = (byte)readPort.ReadByte();
                    byte sender = (byte)readPort.ReadByte();
                    ushort dataLenght = BitConverter.ToUInt16(
                        new byte[] { (byte)readPort.ReadByte(), (byte)readPort.ReadByte() }, 0);
                    byte option1 = (byte)readPort.ReadByte();
                    byte option2 = (byte)readPort.ReadByte();
                    ushort crc = BitConverter.ToUInt16(
                        new byte[] { (byte)readPort.ReadByte(), (byte)readPort.ReadByte() }, 0);

                  // Счетчик количества итерация цикла while
                  int count = 0;
                  while (readPort.BytesToRead < dataLenght)
                  {
                      count++;
                      Thread.Sleep(_sleepTime);
                      if (count > dataLenght)
                      {
                          break;
                      }
                  }

                    byte[] data = new byte[dataLenght];
                    readPort.Read(data, 0, dataLenght);

                    var packet = new Packet.Packet(new Header(recipient, sender, option1, option2), data);

                    if (_isServer)
                    {
                        if (packet.Header.Crc == crc)
                        {
                            if (packet.Header.Recipient != ClietnId || packet.Data.Type == DataType.BroadcastText)
                            {

                              //  _clientArray[0].SendPacketNow(packet);

                                _routerQueue.Enqueue(packet);

                                // if ((packet.Data.Type == DataType.Text || packet.Data.Type == DataType.BroadcastText) && packet.Header.Option1 != PacketOption1.Acknowledge)  // До обновления бродкастинга

                                // Если пакет текстовый или пакет широковешательный и предназначен для этого клиента и это не ACK то пакет парсится
                                if ((packet.Data.Type == DataType.Text || (packet.Data.Type == DataType.BroadcastText && packet.Header.Recipient == ClietnId)) && packet.Header.Option1 != PacketOption1.Acknowledge)
                                {
                                    ParsePacket(packet);
                                }
                                continue;
                            }
                            //Функция разбора пакета
                            ParsePacket(packet);
                        }

                    }
                    else
                    {
                        // Проверка crc и id клиента, то есть предназначен ли этот пакет этому клиенту или пакет является широковешательным
                        // if (packet.Header.Crc == crc && (packet.Header.Recipient == ClietnId || packet.Data.Type == DataType.BroadcastText )) // // До обновления бродкастинга
                        if (packet.Header.Crc == crc && packet.Header.Recipient == ClietnId)
                        {
                            //Функция разбора пакета
                            ParsePacket(packet);
                        }
                    }
                }

                catch (InvalidOperationException)
                {
                    IsPortAvailable(readPort);
                    // Передает событие с текстом ошибки
                  //  OnMessageRecived(new MessageRecivedEventArgs(MessageType.ReadPortUnavailable,  _comPortReader.PortName, 255));
                  //  ReOpenPort(_comPortReader);
                    Thread.Sleep(3000);
                }

                catch (TimeoutException exception)
                {
                }

                catch (Exception exception)
                {
                    LogHelper.GetLogger<CommunicationUnit>().Error("Ошибка при чтение с порта: " + readPort.PortName, exception);
                }

            }
        }
Пример #5
0
        private void ParsePacket(Packet.Packet packet)
        {
            // Функция вовращает true если найдена опция и дальнейший разбор данных не требуется.
                if (ParseOptions(packet))
                {
                    return;
                }

            switch (packet.Data.Type)
            {
                // Обработка пакета текстового сообщения
                case  DataType.Text:
                    {
                        var text = StructConvertor.FromBytes<Text>(packet.Data.Content);

                        // Определяет необходимость разархивирования
                        if (packet.Header.Option2 == PacketOption2.Compressed)
                        {
                            text.Content = Compressor.Unzip(packet.Data.Content);
                        }

                        // Событие передает тип пакета и текст для пользователя
                        OnMessageRecived(new MessageRecivedEventArgs(MessageType.Text, Encoding.UTF8.GetString(text.Content), packet.Header.Sender, packet.Header.Recipient));

                        // Выслать ACK
                        SendAcknowledge(packet);
                    }
                    break;

                // Обработка пакета текстового сообщения
                case DataType.BroadcastText:
                    {
                        var broabroadcastText = StructConvertor.FromBytes<BroadcastText>(packet.Data.Content);

                        // Определяет необходимость разархивирования
                        if (packet.Header.Option2 == PacketOption2.Compressed)
                        {
                            broabroadcastText.Content = Compressor.Unzip(packet.Data.Content);
                        }

                        // Событие передает тип пакета и текст для пользователя
                        OnMessageRecived(new MessageRecivedEventArgs(MessageType.BroadcastText, Encoding.UTF8.GetString(broabroadcastText.Content), packet.Header.Sender, packet.Header.Recipient));

                        // Выслать ACK
                        SendAcknowledge(packet);
                    }
                    break;

                // Обработка пакета запроса на передачу файла
                case DataType.FileRequest:
                    {
                        var fileRequest = StructConvertor.FromBytes<FileRequest>(packet.Data.Content);

                            // Выслать подверждение получения пакета
                            SendAcknowledge(packet);

                            // Если не принимается и не передается файл
                            if (!Client.IsSendingFile && !IsRecivingFile)
                            {
                                var ea = new FileRequestRecivedEventArgs(fileRequest.FileName, fileRequest.FileLenght, packet.Header.Sender);

                                OnFileRequestRecived(ea);

                                _waitFileTransferAnswer = true;

                                // Сохраняет параметры файла
                                _receivingFileName = fileRequest.FileName;
                                ReceivingFileSize = fileRequest.FileLenght;
                                // Сохраняет id отправителя файла
                                _fileSender = packet.Header.Sender;

                                _waitFileTransferAnswerTimer.Change(_waitFileTransferAnswerTimeOut, Timeout.Infinite);
                            }
                            else
                            {
                                SendFileTransferCancel(packet.Header.Sender);

                                // Событие - сообщение о ошибке
                                OnMessageRecived(new MessageRecivedEventArgs(MessageType.Error,
                                                                             "Клиенту № " + packet.Header.Sender +
                                                                             " Было отказано в передачи файла "
                                                                             + fileRequest.FileName + " размером " +
                                                                             fileRequest.FileLenght / 1024 / 1024
                                                                             +
                                                                             "МБ, так как в данный момент уже осуществляется прием другого файла ",
                                                                             0, 0));
                            }
                    }
                        break;

                    // Обработка пакета файла
                    case DataType.FileData :
                    {
                        var fileData = StructConvertor.FromBytes<FileData>(packet.Data.Content);

                        // Если совпал номер пакета и разрешено получение файлов и файл существует и id отправителя совпал с id отправителя файла
                            if (Client.CountOfFilePackets == fileData.PacketNumber && IsRecivingFile &&
                            File.Exists(ReceivingFileFullName) && packet.Header.Sender == _fileSender)
                        {
                            ProcessedFileSize += _filePacketSize;
                            // Устанавливает что пакет получен
                            _waitForFilePacketEvent.Set();
                            // Выслать подверждение получения пакета
                            SendAcknowledge(packet);

                            // Разархивация данных
                          //  fileData.Content = Compressor.Unzip(packet.Data.Content);
                           // var unzipContent = Compressor.Unzip(packet.Data.Content);

                            // Запись данных в файл
                            if (!ByteArrayToFile(ReceivingFileFullName, fileData.Content))
                            {
                                OnMessageRecived(new MessageRecivedEventArgs(MessageType.Error,
                                                                             "Ошибка при записи в файл",
                                                                             packet.Header.Sender, 0));
                                OnMessageRecived(
                                    new MessageRecivedEventArgs(MessageType.FileTransferCanceledRecipientSide,
                                                                _receivingFileName, _fileSender, 0));
                                CancelRecivingFile();
                                break;
                            }

                            // Инкрементирует число принятых пакетов
                            Client.CountOfFilePackets++;
                            // Если пакет последний в цепочке
                            if (fileData.LastPacket)
                            {
                                // Событие о заверщении приема файла
                                OnMessageRecived(new MessageRecivedEventArgs(MessageType.FileReceivingComplete,
                                                                             _receivingFileName, packet.Header.Sender,
                                                                             packet.Header.Recipient));
                                SendFileTransferCompleted(packet.Header.Sender);
                                // Закрывает поток записи файла
                                _fileStream.Close();
                                IsRecivingFile = false;
                            }
                        }
                        else
                        {
            #if DEBUG
                            // Событие - сообщение о ошибке
                            OnMessageRecived(new MessageRecivedEventArgs(MessageType.Error,
                                                                         "Пакет файла: не совпал номер пакета, принятый номер " +
                                                                         fileData.PacketNumber +
                                                                         "сохраненый номер " + Client.CountOfFilePackets,
                                                                         packet.Header.Sender, 0));
            #endif
                        }

            }
                        break;

                case DataType.Initialization:
                    {
                        // Выслать подверждение получения пакета
                        SendAcknowledge(packet);
                    }
                    break;

            }
        }
Пример #6
0
 public bool SendPacketNow(Packet.Packet packet)
 {
     if (!TryWrite(ComPortWriter, packet))
     {
         // Передает событие с текстом ошибки
        // OnAcknowledgeRecived(new MessageRecivedEventArgs(MessageType.Error, "Порт " + _comPortWriter.PortName + " недоступен, отправка невозможна.", 0));
         return false;
     }
     return true;
 }
Пример #7
0
        public bool AddPacketToQueue(object data, byte sender, byte option1 = 0x00, byte option2 = 0x00, bool sendPacketImmediately = false)
        {
            Packet.Packet packet = new Packet.Packet(new Header(Id, sender, option1, option2), data);

            // TO DO: Поправить логику условий
            // Валидация данных
            if (sendPacketImmediately)
            {
                if (!TryWrite(ComPortWriter, packet))
                {
                    // Передает событие с текстом ошибки
                    OnAcknowledgeRecived(new MessageRecivedEventArgs(MessageType.Error, "Порт " + ComPortWriter.PortName + " недоступен, отправка невозможна.", 0,0));
                }
                return true;
            }

            if (packet.Data.Type == DataType.FileData)
            {
                OutFilePacketsQueue.Enqueue(packet);
                return true;
            }

            //Добавляем пакет в очередь на отправку
            OutMessagesQueue.Enqueue(packet);
            return true;
        }
Пример #8
0
 public static bool TryWrite(SerialPort port, Packet.Packet packet)
 {
     try
         {
             lock (port)
             {
                 port.Write(packet.ToByte(), 0, packet.ToByte().Length);
             }
             return true;
         }
         catch (Exception exception)
         {
             LogHelper.GetLogger<Client>().Error("Не удалось произвести запись в порт: " + port.PortName, exception);
             CommunicationUnit.IsPortAvailable(port);
             CommunicationUnit.ReOpenPort(port);
             return false;
         }
     return false;
 }