Я не совсем уверен, что вы пытаетесь сделать, но я думаю, что ваш сервер работает в основном так:
- Прочитать команду (одна строка).
- Отправить полный ответ сразу.
Учитывая, что вы используете pending
, который только проверяет, все ли еще есть расшифрованные данные в сокете SSL, я предполагаю, что вы предполагаете, что если данные отправляются сервером в одном sent
, то они будут прочитаны клиентом тоже сразу. Но это не так. То, что на самом деле происходит здесь, выглядит примерно так:
- Сервер отправляет много суток, скажем, 20000 байт.
- На уровне SSL это как минимум две записи SSL, поскольку одна запись может иметь размер только 16384. Таким образом, предположим, что она сделает запись 16384 и запись для остальных (3616 байт).
-
ssl_socket.revc(RECV_BUFFER)
будет по крайней мере считывать столько данных из базового TCP-соединения, сколько ему нужно для полной записи SSL. Затем он расшифрует запись SSL и вернет не более RECV_BUFFER
байт дешифрованных данных.
ssl_socket.pending()
сообщит вам, если в сокете SSL все еще есть непрочитанные расшифрованные данные. Он не будет проверять, доступны ли данные в базовом сокете TCP. Если в сокете SSL все еще есть данные, следующий ssl_socket.recv(...)
вернется из этих данных, но не будет пытаться прочитать больше данных из основного сокета TCP. Только если в сокете SSL больше нет дешифрованных, но непрочитанных данных, recv
будет читать больше из базового сокета TCP - но в этом случае pending
вернет false, поэтому вы никогда не будете пытаться читать больше данных.
Это означает, что может случиться так, что только первая запись SSL будет прочитана, расшифрована и возвращена в ваш recv
. Таким образом, если вы отправите следующую команду, вы не получите новый ответ, но фактически прочитаете оставшиеся данные ответа из предыдущего запроса.
Чтобы исправить код, вам нужно исправить свое предположение: SSL должен рассматриваться как поток данных, а не как протокол сообщений (то же самое для TCP). Это означает, что вы не можете предполагать, что сообщение будет прочитано полностью и что оно будет возвращено полностью или что оно меньше всего уже полностью в объекте SSL. Вместо этого вам нужно либо заранее знать размер ответа (например, добавить в ответ префикс с длиной), либо иметь какой-то четкий маркер окончания ответа и читать его до этого маркера.