Проблемы с получением "больших" TCP-сообщений - PullRequest
0 голосов
/ 24 февраля 2020

У меня проблема с получением сообщений TCP, размер которых превышает 8000+ (вероятно, 8192) байтов.

Кто-нибудь знает, что я делаю неправильно или отсутствует? Это может быть проблема с буфером или временем?

Код (ниже) отлично работает для сообщений ниже этого «лимита».

Первые 64 байта сообщения - это заголовок, содержащий общее сообщение длина. Только первые 16 байтов заголовка доступны для чтения. Байт 0 равен 0x46 ('F'). Байт 1 в этот момент не обрабатывается. Байт 2 и 3 - это длина сообщения после заголовка. Байты 4-7 в этот момент не обрабатываются. Байты 8-15 все нули. Байт 16-63 и данные после заголовка шифруются.

Каждое сообщение подтверждается получателем с использованием порядковых номеров. Когда любая часть отправляет новое сообщение, она увеличивает свой порядковый номер. Существует только одно сообщение от любой активной части одновременно, прежде чем можно будет отправить следующее сообщение, необходимо подтвердить предыдущее.

Если порядковые номера не складываются, связь сбрасывается.

Обычно размер сообщений варьируется от 64 до 10 Кбайт.

При получении больших сообщений первая проверка сообщения (начиная с 'F' и длины в диапазоне) завершается неудачно и приводит к возврату.

Содержимое bytes является мусором при проверке (точка останова) в операторе return.

Проверка IOHandler->InputBuffer показывает, что он содержит действительные данные (однако это происходит через некоторое время после перерыва).

Использование Wireshark (фильтр: хост, нет arp), я вижу, что сообщение, отправленное с другой стороны, вменяемое. Он разбит на куски по 1460 байт и один меньше, все подтверждается, и никаких других сообщений не происходит.

В приведенном ниже коде отсутствует разбор и шифрование / дешифрование сообщений, но в остальном он несколько завершен. Чтобы гарантировать, что порядковые номера поддерживаются / обрабатываются должным образом, а сообщения о подтверждении для удаленной части имеют приоритет, весь прием и отправка осуществляются этим методом.

void __fastcall TForm1::TCPServerExecute(TIdContext *AContext)
{
   try
   {
      if(AContext->Connection->IOHandler->InputBufferIsEmpty())
         AContext->Connection->IOHandler->CheckForDataOnSource(100);

      if(!AContext->Connection->IOHandler->InputBufferIsEmpty())
      {
         try
         {
            unsigned short msglen;
            unsigned char* puch = (unsigned char*)&msglen;
            TIdBytes bytes;
            TIdBytes Data;
            int DataLength;
            unsigned char digest[20];

            bytes.Length = 64;
            AContext->Connection->IOHandler->ReadBytes(bytes,64,false);  // read header
            puch[0]= bytes[3];        // Endianess
            puch[1]= bytes[2];
            msglen = msglen & 0x1FF;  // block count of data section each block 16 bytes maximum 640

            if(bytes[0] != 0x46 || msglen > 640)
               return;

            Data.Length = msglen * 16;

            if(msglen)
              AContext->Connection->IOHandler->ReadBytes(Data,DataLength,false);   // read data section

           TMessage Msg = ValidMessage(bytes, Data);
           if(Msg->IsAckMsg)
           {
              TList* list = txList->LockList();
              if(list->Count)
              {
                 for(int i=0; i < list->Count; i++)
                 {
                    TMessage* msg = (TMessage*)list->Items[i];
                    if(Msg->RSeqNo == msg->RSeqNo)
                    {
                       list->Delete(i);
                       delete msg;
                       break;
                    }
                 }
              }
              txList->UnlockList();
           }
           else
           {
              TMessage ACKMsg = Msg->MakeACK();
              TIDBytes senbytes;
              int Msglen = ACKMsg->Prepare(sendbytes);
              AContext->Connection->IOHandler->Write(sendbytes, MsgLen);
              rxList->Add(Msg);
              LogMsg(ACKMsg);
              PostMessage(this->Handle, MSG_UPDATE, NULL, 1);
           }    
         }
         catch(Exception& E)
         {
         }
      }
      else
      {
         TMessage* Msg = NULL;
         TList* list = txList->LockList();
         if(list->Count)
            Msg = (TMessage*)list->Items[0];
         txList->UnlockList();

         if(Msg)
         {
            if(Msg->fMsgSent)
               return;
            TIDBytes bytes;
            int Msglen = Msg->Prepare(bytes);
            AContext->Connection->IOHandler->Write(bytes, MsgLen);
            Msg->fMsgSent = true;
         }
      }
   }
   catch (Exception& E)
   {
   }

Краткое содержание Wireshark

Message received correct
1   0.000000    192.168.1.202   192.168.1.72    TCP 342 52000 ? 55496 [PSH, ACK] Seq=1 Ack=1 Win=63080 Len=288      // Command request to remote part
2   0.030413    192.168.1.72    192.168.1.202   TCP 117 55496 ? 52000 [PSH, ACK] Seq=1 Ack=289 Win=11680 Len=63     // Command acknowledged by remote part 
3   0.031360    192.168.1.72    192.168.1.202   TCP 60  55496 ? 52000 [PSH, ACK] Seq=64 Ack=289 Win=11680 Len=1
4   0.031444    192.168.1.202   192.168.1.72    TCP 54  52000 ? 55496 [ACK] Seq=289 Ack=65 Win=63016 Len=0
5   0.050135    192.168.1.72    192.168.1.202   TCP 1514    55496 ? 52000 [PSH, ACK] Seq=65 Ack=289 Win=11680 Len=1460  // Respons from remote part beginning with 0x46 0x01 0x01 0xee
                                                                    // Gives total message length 64 + 494*16 = 7968
6   0.051363    192.168.1.72    192.168.1.202   TCP 1514    55496 ? 52000 [PSH, ACK] Seq=1525 Ack=289 Win=11680 Len=1460
7   0.051424    192.168.1.202   192.168.1.72    TCP 54  52000 ? 55496 [ACK] Seq=289 Ack=2985 Win=64240 Len=0
8   0.053059    192.168.1.72    192.168.1.202   TCP 1514    55496 ? 52000 [PSH, ACK] Seq=2985 Ack=289 Win=11680 Len=1460
9   0.053860    192.168.1.72    192.168.1.202   TCP 1514    55496 ? 52000 [PSH, ACK] Seq=4445 Ack=289 Win=11680 Len=1460
10  0.053910    192.168.1.202   192.168.1.72    TCP 54  52000 ? 55496 [ACK] Seq=289 Ack=5905 Win=64240 Len=0
11  0.055217    192.168.1.72    192.168.1.202   TCP 1514    55496 ? 52000 [PSH, ACK] Seq=5905 Ack=289 Win=11680 Len=1460
12  0.056023    192.168.1.72    192.168.1.202   TCP 722 55496 ? 52000 [PSH, ACK] Seq=7365 Ack=289 Win=11680 Len=668 // Last response chunk
13  0.056091    192.168.1.202   192.168.1.72    TCP 54  52000 ? 55496 [ACK] Seq=289 Ack=8033 Win=64240 Len=0
14  0.056428    192.168.1.202   192.168.1.72    TCP 118 52000 ? 55496 [PSH, ACK] Seq=289 Ack=8033 Win=64240 Len=64  // Respons acknowledged
15  0.057674    192.168.1.72    192.168.1.202   TCP 60  55496 ? 52000 [ACK] Seq=8033 Ack=353 Win=11680 Len=0

Message not received correct
1   0.000000    192.168.1.202   192.168.1.72    TCP 342 52000 ? 55501 [PSH, ACK] Seq=1 Ack=1 Win=62952 Len=288      // Command request to remote part
2   0.034937    192.168.1.72    192.168.1.202   TCP 117 55501 ? 52000 [PSH, ACK] Seq=1 Ack=289 Win=11680 Len=63     // Command acknowledged by remote part
3   0.035910    192.168.1.72    192.168.1.202   TCP 60  55501 ? 52000 [PSH, ACK] Seq=64 Ack=289 Win=11680 Len=1
4   0.035961    192.168.1.202   192.168.1.72    TCP 54  52000 ? 55501 [ACK] Seq=289 Ack=65 Win=62888 Len=0
5   0.056781    192.168.1.72    192.168.1.202   TCP 1514    55501 ? 52000 [PSH, ACK] Seq=65 Ack=289 Win=11680 Len=1460  // Respons from remote part beginning with 0x46 0x01 0x02 0x33
                                                                    // Gives total message length 64 + 563*16 = 9072
6   0.058048    192.168.1.72    192.168.1.202   TCP 1514    55501 ? 52000 [PSH, ACK] Seq=1525 Ack=289 Win=11680 Len=1460
7   0.058083    192.168.1.202   192.168.1.72    TCP 54  52000 ? 55501 [ACK] Seq=289 Ack=2985 Win=64240 Len=0
8   0.059735    192.168.1.72    192.168.1.202   TCP 1514    55501 ? 52000 [PSH, ACK] Seq=2985 Ack=289 Win=11680 Len=1460
9   0.060575    192.168.1.72    192.168.1.202   TCP 1514    55501 ? 52000 [PSH, ACK] Seq=4445 Ack=289 Win=11680 Len=1460
10  0.060604    192.168.1.202   192.168.1.72    TCP 54  52000 ? 55501 [ACK] Seq=289 Ack=5905 Win=64240 Len=0
11  0.062111    192.168.1.72    192.168.1.202   TCP 1514    55501 ? 52000 [PSH, ACK] Seq=5905 Ack=289 Win=11680 Len=1460
12  0.063037    192.168.1.72    192.168.1.202   TCP 1514    55501 ? 52000 [PSH, ACK] Seq=7365 Ack=289 Win=11680 Len=1460
13  0.063061    192.168.1.202   192.168.1.72    TCP 54  52000 ? 55501 [ACK] Seq=289 Ack=8825 Win=64240 Len=0
14  0.063804    192.168.1.72    192.168.1.202   TCP 365 55501 ? 52000 [PSH, ACK] Seq=8825 Ack=289 Win=11680 Len=311
15  0.063805    192.168.1.72    192.168.1.202   TCP 60  55501 ? 52000 [PSH, ACK] Seq=9136 Ack=289 Win=11680 Len=1   // Last response chunk
16  0.063839    192.168.1.202   192.168.1.72    TCP 54  52000 ? 55501 [ACK] Seq=289 Ack=9137 Win=63928 Len=0
No acknowledge as meesage not received correct.

1 Ответ

0 голосов
/ 26 февраля 2020

Иногда этого достаточно другими глазами. Маска 1FF неверна, при замене на правильную 3FF она работает до сих пор. Спасибо за ваши острые глаза.

...