Препредаване на полузатваряне на TCP след източване на чакащите байтове
Работете с EOF в TCP прокси, без да губите данни от опашката и без да прекъсвате отговора в другата посока.
Клиентът приключва изпращането, проксито вижда EOF и отговорът изчезва. Незабавното затваряне на двата прокси сокета може да предизвика точно тази последователност. В TCP реле вподреденият край в една посока не означава, че другата посока е приключила.
Помислете за клиент, който изпраща заявка, затваря своята страна за изпращане и чака отговора:
client -- request, then FIN --> proxy --> service
client <-------- reply ------- proxy <-- service
Проксито има две TCP връзки и два независимо движещи се байтови потока. То трябва да пренесе нататък указанието за край на входа, след като пренесе байтовете преди него.
Източете опашката, преди да препредадете EOF
При приемане с ненулев размер в TCP поток връщането на нула означава вподреден край на този входящ поток. Отбележете тази посока на четене като приключена. Спрете да чакате повече входни данни от нея, но запазете байтовете, вече поставени в опашката за отсрещния сокет.
След като опашката от клиента към услугата се източи, извикайте shutdown(service_socket, SHUT_WR) върху POSIX сокет. Това прекратява по-нататъшното предаване към услугата, като оставя посоката от услугата към клиента достъпна. Когато услугата приключи отговора си, приложете огледалната операция след източване на опашката на отговора.
Затварянето на дескрипторите принадлежи към момента, в който и двете посоки и техните чакащи буфери са приключили, или когато грешка или отказ изискват прекратяване. Поддържайте ограничен таймаут за партньор, който никога не завършва останалата си половина.
Готовността е покана за четене
Четим сокет може да има данни или състояние EOF. Извикайте recv и интерпретирайте резултата. Положителните бройки са байтове за препредаване; нулата е краят на посоката. При неблокиращ сокет EAGAIN или EWOULDBLOCK означава, че в момента няма повече входни данни, докато EINTR може да изисква повторен опит. Нито едно от двете не е същото събитие като EOF.
Не търсете флаг FIN във върнатия буфер от байтове. TCP доставя вподреден поток от байтове към този API; границите на пакетите и FIN сегментът не са обикновен полезен товар на приложението.
Това е жизненият цикъл на един суров байтов тунел. HTTP прокси, което анализира съобщения, все още трябва да спазва HTTP рамкирането, а прокси, което прекратява TLS, има и протокол за затваряне на TLS. Дръжте тези протоколни решения над насоченото TCP реле.