Вызывает ли проблема произвольное манипулирование потоком TCP-соединений?

Когда мой HTTP-прокси был простым многопоточным, запросы GET и CONNECT работали нормально: теперь я хочу разместить в середине диалога TCP между клиентами и серверами механизм организации очередей, в котором проталкиваются байты, поступающие от клиента и серверов. очереди с приоритетами, и только данные с наивысшим приоритетом извлекаются из очередей и отправляются по назначению.

Эффективные данные, которые я получил от recv()с клиентов и серверов хранится в struct infoPkt вместе с некоторыми метаданными:

typedef struct infoPacket {
int clientFd;
int serverFd;
int request;
int direction;
int priority;
char payload[MAX_PAYLOAD_SIZE];
int payloadSize;
in_addr_t serveraddr;
char host[256];
std::chrono::time_point<std::chrono::system_clock> start;
bool first;
bool last;
} infoPkt;

Я не могу опубликовать весь код здесь, это слишком много. Я постараюсь объяснить поток пакета infoPkt в моей программе:

У меня есть следующие классы:

  • ClientManager: цикл с accept(), получая HTTP-запрос от клиента, создаю первый infoPkt этой связи с запросом внутри него и помещая его в очереди prio DequeManager::getInstance().insert(newElem);, Начните accept()снова

  • HTTPManager: этот класс, какие методы все staticзанимается реальным обменом данными между клиентом и сервером; HTTPManager::dealPkt(infoPkt p) вызывается из DequeManager, связывая это с queueingThread нить (см. DequeManager ниже), когда первый пакет соединения удален; после отправки 200 OK к клиенту, я сselect() клиентский и серверный fds для проверки входящих данных; что я recv()Вставляю в прио очереди в DequeManager; Если я recv() 0 байтов от клиента или сервера, я создаю infoPkt без полезной нагрузки, но с infoPkt.last установлен в true а также break select() петля;

  • DequeManagerздесь работают два потока, один зацикливается на проверку на голодание (если пакет провел слишком много времени в очереди, он будет перемещен в очередь с более высоким приоритетом), а другой всегда сначала удаляет пакеты из очереди с более высоким приоритетом, затем из очередей с более низким значением prio, когда высший из них пуст; когда нить удаляет infoPktУ нас есть два сценария:

    1. serverFd в infoPkt -1: это означает, что это пакет HTTP-запроса, соединение по-прежнему не установлено, так как у меня нет дескриптора файла сервера; удаление темы делает socket(), bind() а также connect() на удаленный сервер, установите новый сервер fd в infoPkt.serverFd, звонки std::thread queueingThread(HTTPManager::dealPkt, packet); queuingThread.detach(); и продолжает убирать снова;

    2. serverFd в infoPkt > 0: это означает, что это infoPkt принадлежность к уже существующему соединению, помещенному в очередь клиентом или сервером; сначала я проверяю infoPkt.last флаг, если это true это последний пакет соединения, recv()IN с клиента или сервера вернул 0, поэтому я создал это infoPkt без payload но установка infoPkt.last в trueтак что я выполняю close(infoPkt.clientFd); а также close(infoPkt.serverFd);; в противном случае, если infoPkt.serverFd > 0 и infoPkt.last не является trueэтот пакет будет отправлен в пункт назначения infoPkt.direction,

«Манипулирование потоком», которое я написал в заголовке, относится к обмену данными в select()в соединении HTTP CONNECT: данные, которые я получаю от клиента, не отправляются на сервер сразу, а помещаются в очереди prio и отправляются позже, только когда поток удаления удалит эти данные, потому что, согласно механизмам приоритета, соблюдаются условия, чтобы сообщить это его очередь. В то время как мой предыдущий прокси-сервер с немедленной пересылкой данных в пункт назначения при получении данных прошел нормально: я пытаюсь согласовать механизм приоритетов между ними, задерживая обмен данными, но программы работают не так, как я ожидал; Соединение закрывается после отправки одного или двух пакетов, и я не могу понять, почему.

Вот вывод моей программы, когда я пытаюсь подключиться к домашней странице Netflix.

Created ClientManager
Start PROXY, thread id 67426496
Number of interfaces (or their IP addr) has changed, mmap() again
Found new interfaces: wlan0[192.168.1.88]
priority 1 to hostname www.netflix.com
priority 1 to hostname nflxvideo.net
priority 2 to hostname www.youtube.com
priority 2 to hostname googlevideo.com
priority 3 to hostname www.facebook.com
remover thread with method DequeManager::removeAll() detached
controller thread with method DequeManager::aging() detached
67426496 THREAD MAIN
Proxy listening to port 8000, here we go!

67426496 ClientManager::getRequestFromClient received from client 215 byte
67426496 ClientManager::manageClient() inserted C 4, S -1, CONNECT, UPLOAD, prio 1, size 215, host www.netflix.com, first 1, last 0 --->
CONNECT www.netflix.com:443 HTTP/1.1
Host: www.netflix.com:443
Proxy-Connection: keep-alive
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.3667426496 ClientManager::getRequestFromClient received from client 215 byte
67426496 ClientManager::manageClient() inserted C 5, S -1, CONNECT, UPLOAD, prio 1, size 215, host www.netflix.com, first 1, last 0 --->
CONNECT www.netflix.com:443 HTTP/1.1
Host: www.netflix.com:443
Proxy-Connection: keep-alive
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36111642368 DequeManager::removeAndDealPkt created pair (4 7)
137008896 HTTPManager::dealPkt() thread 137008896 started
137008896 HTTPManager::dealPkt() dealing with socket fd pair (4 7)
137008896 HTTPManager::dealPkt [CONNECT] sent 200 OK to client
137008896 HTTPManager::dealPkt [CONNECT] max fd+1 between client 4 and server 7: 8
137008896 HTTPManager::dealPkt [CONNECT] queued up pkt from client, 209 bytes
111642368 DequeManager::removeAndDealPkt created pair (5 8)
111642368 DequeManager::removeAndDealPkt send() C 4, S 7, CONNECT, UPLOAD, prio 1, size 209, host www.netflix.com, first 0, last 0
145401600 HTTPManager::dealPkt() thread 145401600 started
145401600 HTTPManager::dealPkt() dealing with socket fd pair (5 8)
145401600 HTTPManager::dealPkt [CONNECT] sent 200 OK to client
145401600 HTTPManager::dealPkt [CONNECT] max fd+1 between client 5 and server 8: 9
111642368 DequeManager::removeAndDealPkt sent_bytes 209
145401600 HTTPManager::dealPkt [CONNECT] queued up pkt from client, 209 bytes
111642368 DequeManager::removeAndDealPkt send() C 5, S 8, CONNECT, UPLOAD, prio 1, size 209, host www.netflix.com, first 0, last 0
111642368 DequeManager::removeAndDealPkt sent_bytes 209
137008896 HTTPManager::dealPkt [CONNECT] recv() 0 from client, crafting last packet 4 7
137008896 HTTPManager::dealPkt dealPkt() thread terminated
145401600 HTTPManager::dealPkt [CONNECT] recv() 0 from client, crafting last packet 5 8
145401600 HTTPManager::dealPkt dealPkt() thread terminated
111642368 DequeManager::removeAndDealPkt get LAST PACKET, closing fds 4 and 7
111642368 DequeManager::removeAndDealPkt get LAST PACKET, closing fds 5 and 8
67426496 ClientManager::getRequestFromClient received from client 215 byte
67426496 ClientManager::manageClient() inserted C 6, S -1, CONNECT, UPLOAD, prio 1, size 215, host www.netflix.com, first 1, last 0 --->
CONNECT www.netflix.com:443 HTTP/1.1
Host: www.netflix.com:443
Proxy-Connection: keep-alive
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36111642368 DequeManager::removeAndDealPkt created pair (6 5)
145401600 HTTPManager::dealPkt() thread 145401600 started
145401600 HTTPManager::dealPkt() dealing with socket fd pair (6 5)
145401600 HTTPManager::dealPkt [CONNECT] sent 200 OK to client
145401600 HTTPManager::dealPkt [CONNECT] max fd+1 between client 6 and server 5: 7
145401600 HTTPManager::dealPkt [CONNECT] queued up pkt from client, 215 bytes
111642368 DequeManager::removeAndDealPkt send() C 6, S 5, CONNECT, UPLOAD, prio 1, size 215, host www.netflix.com, first 0, last 0
111642368 DequeManager::removeAndDealPkt sent_bytes 215
145401600 HTTPManager::dealPkt [CONNECT] recv() 0 from client, crafting last packet 6 5
145401600 HTTPManager::dealPkt dealPkt() thread terminated
111642368 DequeManager::removeAndDealPkt get LAST PACKET, closing fds 6 and 5
^CCaught signal 2

Если кто-то скажет: «Это неправильно, потому что обмен данными в TCP-соединении не должен задерживаться вручную из-за вашего механизма приоритетов», я выброшу свой код и успокоюсь, найдя другой способ добиться этого. управление трафиком в соединении TCP, пакет за пакет; Искренне, я бы предпочел, чтобы кто-то сказал мне: «Вы, придурок, просто проверьте это, и все будет работать», поэтому я знаю, что я не потрачу впустую месяцы на этот мой любительский проект: D

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

-1

Решение

Проблема в том, что TCP имеет явный механизм фиксировать переупорядочение проблем. Это может включать в себя NACK, которые заставляют отправителя повторно отправлять пакеты.

Ваше «приоритетное» переупорядочение байтов в потоке TCP будет в лучшем случае создайте много повторной отправки данных, поэтому ваш «приоритет» ухудшает все. Но вполне возможно, что любая сторона просто сдается, когда поток TCP слишком нарушен.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]