TCP连接流的任意操作是否会导致问题?

时间:2017-01-25 11:38:56

标签: c++ multithreading sockets tcp http-proxy

当我的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队列中{{ 1}},再次启动DequeManager::getInstance().insert(newElem);;

  • accept():此类,所有方法都是HTTPManager,处理客户端和服务器之间的实际数据交换;从static调用HTTPManager::dealPkt(infoPkt p),当第一个连接数据包被删除时,将DequeManagerqueueingThread线程相关联(请参阅下面的DequeManager);在向客户端发送200 OK之后,我使用select()客户端和服务器fds循环检查传入的数据;我在recv()中的prio队列中插入了DequeManager;如果来自客户端或服务器的recv() 0字节,我制作的infoPkt没有有效负载但infoPkt.last设置为truebreakselect() }} loop;

  • DequeManager:两个线程在这里工作,一个是循环检查饥饿(如果数据包在队列中花费了太多时间,它将被移动到具有更高优先级的队列中)和另一个总是先从优先级较高的队列中删除数据包,然后从较高优先级的队列中删除较高优先级的队列;当线程删除infoPkt时,我们有两种情况:

      serverFd中的
    1. infoPkt为-1:这意味着这是HTTP请求数据包,还没有建立连接,因为我没有关联的服务器文件描述符;移除线程将socket()bind()connect()添加到远程服务器,将新服务器fd设置为infoPkt.serverFd,调用std::thread queueingThread(HTTPManager::dealPkt, packet); queuingThread.detach();并继续删除;

    2. {li>

      serverFd infoPkt中的infoPkt是&gt; 0:这意味着这是属于已存在的连接的infoPkt.last,由客户端或服务器推入队列;首先,我检查true标志,如果它是recv()这是连接的最后一个数据包,infoPkt从客户端或服务器返回0,所以我制作了这个payload没有infoPkt.lasttrue设置为close(infoPkt.clientFd);,因此我执行了close(infoPkt.serverFd);infoPkt.serverFd;否则,如果infoPkt.last是&gt; 0和true不是infoPkt.direction,此数据包将被发送到目的地检查select()

我在标题中写的“流操作”是指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.36 67426496 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.36 111642368 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.36 111642368 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 中的数据交换,在CONNECT HTTP连接中:我从客户端获取的数据不会立即发送到服务器,而是推送到prio队列中并且稍后发送,只有当移除线程将删除该数据时,因为根据优先级机制,满足条件告诉它轮到它。虽然我以前的代理服务器在接收到数据时立即将数据转发到目的地但是我正在尝试在两者之间安装优先级机制,延迟数据交换,但程序不能按预期工作;发送一个或两个数据包后连接自行关闭,我无法弄清楚原因。

当我尝试连接到Netflix主页时,这是我程序的输出。

import FreeCAD as fc
print(fc)
assert False

如果有人会说“这是错误的,因为预计TCP连接中的数据交换不会被你的优先级机制从内部手动延迟”,我会抛弃我的代码,让我放心,找到另一个在TCP连接中实现流量控制的方式,每包数据包;真诚地,我希望有人对我说“你这个白痴,只要检查一下,一切都会有效”,所以我知道我不会浪费几个月的时间在这个业余项目上:D

编辑:如果您有任何问题可以随意提问,我只提供项目中有意义的代码。 Here's my Gist

1 个答案:

答案 0 :(得分:0)

问题是TCP有一个明确的修复重新排序问题的机制。这可能涉及NACK,它会强制发送方重新发送数据包。

您的优先级&#34;重新排序TCP流中的字节将充其量创建大量数据重新发送,因此您的优先级&#34;降低一切。但是,当TCP流过于中断时,任何一方都放弃了,这很可能。