Заморозка программы, если буфер, выделенный для TTCPClient.ReceiveBuf, имеет точный размер возвращаемого пакета данных. - PullRequest
1 голос
/ 25 февраля 2011

Я использую TTphClient Delphi в модуле sockets.pas для подключения к службе TCP.

Когда я пытаюсь получить ответ от службы TCP, я кодирую следующим образом:

var gap: integer;
    T: TTCPClient;
    B: TBytes;
    i: integer;
begin
  ...
  gap := 10;
  SetLength(B, gap);
  i := 0;

  repeat
    i := T.ReceiveBuf(B[i], gap);
    if (i > 0) and (i < gap) then begin
      SetLength(B, Length(B) - (gap - i));
      Break;
    end else if (i > 0) then begin
      i := Length(B);
      SetLength(B, i + gap);
    end;
  until i = 0;
  ...
end;

Я использую целочисленную переменную gap, чтобы контролировать размер буфера, считываемого из сокета.В этом примере разрыв составляет 10. Программа запустится без проблем, если размер приема не будет множителем разрыва (10).например, 4, 15, 29.

Однако программа будет зависать в ReceiveBuf, если буфер в сокете умножен на 10. Например: 10, 20, 30.

Как мне кодироватьс TTCPClient, чтобы он работал для любого возвращенного размера буфера, и моя программа не зависнет наполовину?

Я использую режим bmBlocking для этого клиентского сокета.

Спасибо.

Ответы [ 4 ]

0 голосов
/ 28 февраля 2011

Используйте необработанный вызов сокета, чтобы найти любые доступные данные для чтения, если recv (ваш сокет, nil, 0, MSG_PEEK)> 0 затем ...

0 голосов
/ 25 февраля 2011

Поскольку вы используете блокирующий сокет, вызов ReceiveBuf, когда нечего принимать, будет зависать, пока что-то не будет записано в сокет.

Если вы получите 10 байтов и прочитаете 10-байтовые куски, после вашего первогопрочитано, вы прочитали 10 байт, поэтому оно не соответствует условию (i > 0) and (i < gap), но соответствует (i > 0), поэтому вы выполняете второе чтение для пустого сокета, и поскольку сокет блокируется, вы зависаете тампока не получен другой пакет.

Теперь у меня нет особого опыта с блокировкой сокетов ... но я бы предположил, что использование T.ReceiveLength = 0 в качестве условия цикла вместо (i = 0) может помочь.

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

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

0 голосов
/ 25 февраля 2011

Всегда проверяйте результат из ReceiveBuf.В случае ошибки результат будет SOCKET_ERROR (который объявлен в WinSock как -1).Ваш код не обрабатывает этот случай и продолжит выполнение цикла.

Вы можете вызвать WSAGetLastError , чтобы определить определенный код ошибки .Например, сервер может закрыть соединение после отправки всех своих данных, что будет указано кодом ошибки WSAECONNRESET.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...