У меня проблема с получением сообщений 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.