0

我很难在 C 中实现代理服务器。它适用于一些最初的网页,但在等待新请求时我被阻止了。

设计:

Firefox -> Proxy -> Webserver --.
Firefox <- Proxy <- Webserver <-'

所以每个请求都是从浏览器到代理和服务器然后返回的往返。在请求的响应返回之前,什么都不会发生。我不使用流水线、线程recv()或类似的东西,而只send()使用线性串行方式(为了简单和直观)。我也没有关闭任何套接字,因为我想要一个持久连接

我希望能够获取一个完整的网页,包括 css、img、js 等子请求的资源。

在我的实现中,我设法获取了一些对网页的第一个请求。然后它在第 1 步挂起

执行:

puts("Waiting for user to connect..");
int sock_user = accept(sock, (struct sockaddr*)NULL, NULL);
int sock_host = -1;
printf("User connected.\n");


// Accept requests
while(1){

   http_request req;
   http_response resp;


   // 1. Client ==> Proxy     Server
   http_parse_request(sock_user, &req);                         // uses recv()

   // 2. Client     Proxy ==> Server
   if (sock_host < 0)
      sock_host = proxy_connect_host(req.header->host);
   write(sock_host, req.header->raw_data, req.header->raw_size);

   // 3. Client     Proxy <== Server
   http_parse_response(sock_host, &resp);                      // uses recv()

   // 4. Client <== Proxy     Server
   write(sock_user, resp.header->raw_data,          resp.header->raw_size);
   write(sock_user, resp.body  ->first_block->data, resp.body  ->first_block->size);

}

日志:

     ---- ......................................... ----

     ---- after succesfully responded to 4 requests ----


Client ==> Proxy     Server
                                Received              389

Client     Proxy ==> Server
                                Sending..             389
                                Sent                  389

Client     Proxy <== Server
                                Got header            312
                                Got body              1437
                                Response total        1749

Client <== Proxy     Server
                                Sending header..      312
                                Sent                  312
                                Sending body..        1437
                                Sent                  1437

Client ==> Proxy     Server


                ---- Hangs/blocks here ----

萤火虫:

在此处输入图像描述

线鲨: 在此处输入图像描述

我不知道该阻塞的原因是什么,并且我花了整整一周的时间试图解决这个问题而没有突破。

在试图解决问题的事情中:

  1. CRLF为每个响应正文发送一些额外的
  2. recv()检查每个和的返回值send()。(在上面的日志中,打印的值是来自recvand send的返回值)

我希望有人至少可以就如何解决这个问题给出一些指导,否则我的大脑很快就会爆炸:)

4

1 回答 1

0

您必须非常小心,不要读取太多数据。例如,确保:

  • 标头只读到双 CRLF;存储额外的数据并与正文一起发送

  • 正文的发送不是在服务器发送完整的标头之前开始(不适用于这种 GET 情况,但对于 POST 或 CONNECT 很重要)

  • 仅从正文接收和发送 Content-Length 字节

这适用于客户端 -> 代理请求和服务器 -> 代理响应。

您的示例代码处于无限循环 ( while (1) ...) 中。你如何中止这个?您是否尊重“代理连接”标头?

于 2013-10-26T14:15:03.317 回答