Пълнодуплексен поток и обратен натиск в SOCKS релей
Проектирайте потока на релея около независими байтови потоци, частичен I/O, ограничени буфери и обратен натиск вместо предположени размери на отговора.
SOCKS ръкостискането успешно приключи. Сега релеят чете от клиента, пише към дестинацията, чака пълен отговор и едва след това отново чете от клиента. Тази последователност може да блокира напълно валидно приложение.
След като TCP тунелът е установен, SOCKS не дефинира съобщенията в него. Дестинацията може да изпрати първа. Двете страни могат да изпращат независимо. Едната страна може да изпрати кратък запис и после да чака отговора на другата.
Преносете байтове, не предполагаеми транзакции
Извикване за получаване връща наличните байтове според флаговете и състоянието на сокета. То не казва на общ релей, че отговорът на приложението е завършен. Чакането произволно голям буфер да се напълни може да попречи на предаването на малкото съобщение, което партньорът трябва да продължи.
Използвайте съществуващия модел на паралелност на приложението, за да обслужвате двете посоки: цикъл на събития, асинхронен I/O или друг умишлено избран дизайн. Важното поведение е напредъкът в една посока да не изисква измислена граница на съобщение в другата.
Поддържайте два ограничени буфера за чакащи данни
Данните, прочетени от клиента, може все още да чакат да стигнат до дестинацията, докато данните от дестинацията чакат да стигнат до клиента. Проследявайте тези чакащи байтове отделно.
Изпращането може да запише по-малко байтове от поисканото. Запазете незаписаната част; не я изхвърляйте и не пускайте отново целия буфер. Временно незаписваем сокет е причина да изчакате правилното събитие за готовност, а не да се въртите непрекъснато.
Ограничете буферите. Ако дестинацията е бавна, продължаването да четете неограничени клиентски данни просто премества опашката в паметта на релея. Обратният натиск означава спиране на четенето, когато съответният буфер е пълен, и възобновяване, когато записът освободи място.
Край в една посока изисква политика
TCP може да затвори посоката за изпращане, докато другата посока все още има полезни данни. Решете как да предадете това състояние, след като буферираните байтове се изчерпят, и различавайте подреденото затваряне от грешка или краен срок.
Нищо от това не изисква релеят да дешифрира или анализира полезния товар на приложението. То се нуждае от правилна обработка на потока. Увеличаването само на размера на буфера не може да поправи релей, който чака грешната страна или приема, че всяко четене отговаря на една цяла заявка.