Winsock - увеличена последовательность повторной передачи

При общении с заказным клиентом я получаю следующее. Под заказным клиентом я имею в виду самодельную печатную плату с ПЛИС, на которой работает трехскоростной Ethernet Intel FPGA IP. Не имеет значения, находится ли переключатель между ПК и платой.

Рабочий процесс, видимый с сервера (ПК с Windows), где я обнаружил это поведение с помощью wirehark:

  1. Подключиться к клиенту (Syn - Syn / Ack - Ack) Winsock2.connect
  2. Отправка данных> MTU с Winsock2.WSASend (4092 байта на MTU 4088 байтов)
  3. Пакет "фрагментируется" на 2 пакета - установлен бит не фрагментировать
  4. Произойдет повторная передача (потому что клиент ответил слишком медленно?)

Я использую delphi 10.4 и функции Winsock2. Перед каждой отправкой я проверяю с помощью select, установлен ли fdwrite, если FD_Isset. Нэгла деактивирован.

«Повторная передача» не происходит каждый раз, и я не мог обнаружить никаких закономерностей, когда они возникают. За исключением случаев, когда клиенту требуется более 30 мс для отправки своего ACK.

Когда происходит «повторная передача», повторно отправляется не пакет 1 или два, а пакет 1 со смещением 60, который является полезной нагрузкой пакета 2. Порядковый номер пакета 1 также увеличивается на 60. Даже данные верны, они правильно увеличиваются на 60. Когда я отправляю 6000 байт, я получаю такое же поведение с увеличенным seq 1968, что тоже правильно. Что здесь происходит? Могу ли я обнаружить это с помощью winsock2? Могу ли я установить RTO с помощью WinSock? Почему увеличивается порядковый номер, а не повторно передается пакет 1 как таковой?

Исходный код функции отправки:

      function TZWinTCPSock.SendData (out ErrMsg : TAPILogStruct; SendOffset : 
Cardinal = 0)  : Boolean;
var
  WSABuff   : WSABUF;
  res       : Integer;
  IPFlags   : Cardinal;
  t         : Cardinal;
  WSAErr    : Cardinal;
begin
  Result      := FALSE;
  WSAErr      := WSAGetLastError;
  try
    if not CheckSockValid(ErrMsg) then // checks if fd_write is set
    begin
      exit(false);
    end;
    try
      WSABuff.len   := FMem.SendLength; // 4092 at this time Cardinal
      WSABuff.buf   := @FMem.SendData[SendOffset]; // 8192 Bytes reserved TArray<Byte>
      IPFlags       := 0;
      res := WSASend(FSocket,@WSABuff,1,FMem.sentBytes,IPFlags,nil,nil);
      if Res <> SOCKET_ERROR then
      begin
        if FMem.SendLength <> FMem.SentBytes then
        begin
          exit(false);
        end
        else
        begin
          Result := TRUE;
          if WSAGetLastError <> WSAErr then // unexpected WSA error
          begin
            exit(FALSE);
          end;
        end;
      end
      else
      begin
        FLastWSAErr       := WSAGetLastError;
        if FLastWSAErr = WSAECONNRESET then
        begin
          Disconnect(ErrMsg);
          exit(false);
        end;
      end;
    except
      on E : Exception do
      begin
        // Some error handling
      end;
    end;
  finally
    
  end;
  
end;

Edit1 У пакетов установлен бит запрета фрагментации. Я попытался обнаружить эту «повторную передачу» с помощью центра администрирования Windows, но ничего не вижу.

1 ответ

Решение

Получил ответ на ответы вопросы иMicrosoft . Похоже, это была проблема зонда потери хвоста, когда хост назначения неисправен, потому что ответ занял слишком много времени, а время ожидания srtt истекло.

Другие вопросы по тегам