2013-04-16 15 views
0

我正在编写一个有问题的页面发送到浏览器的网络服务器。它正确发送第一个文件(该文件包含两个css文件)。但是,在发送第二个文件之后,浏览器停止请求数据。它总是会错过完成页面所需的一个css文件。套接字事务不通过

这里的一些交易的:

GET/HTTP/1.1 
Host: website.com 
Connection: keep-alive 
Cache-Control: max-age=0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko)    Chrome/26.0.1410.43 Safari/537.31 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

HTTP/1.1 OK 200 
Server: thserver 
Date: Mon Apr 15 17:29:51 2013 
Content-Length: 564 

Data received: GET /main.css HTTP/1.1 
Host: website.com 
Connection: keep-alive 
Accept: text/css,*/*;q=0.1 
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko)  Chrome/26.0.1410.43 Safari/537.31 
Referer: http://website.com/ 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

HTTP/1.1 OK 200 
Server: thserver 
Date: Mon Apr 15 17:29:51 2013 
Content-Length: 386 

如果有谁还知道验证的HTTP事务,帮助过的一个好办法。我确实看过了chrome的开发工具,并且显示它正在等待接收最后一个文件,但我似乎从未在服务器上收到请求。

另外,我用telnet模拟浏览器,它工作正常。这是我输入的内容:

GET/
GET /index.css 
GET /main.css 

然后它每次都发送回文件。

代码继续使用read(2)轮询套接字,但在第三个文件的请求应该到达时,一直返回EAGAIN或EWOULDBLOCK。

这里的套接字IO代码:

const int port_number = 80; 
const int timeout  = 5000000; 
const int wait_time  = 10000; 

PORT_CALL { 

    /* declarations here */ 

    read_client: 

    result = read(socket[ 0 ], &header_buffer[ bytes_read ], BUFFER_SIZE - bytes_read); 

    if(result < 0){ 
     if(errno & (EWOULDBLOCK | EAGAIN)){ 

      if(bytes_read > 0){ 

       bytes_read = 0; 
       read_timeout = 0; 
       goto respond_request; 
      } 
      if(read_timeout < timeout){ 
       read_timeout += wait_time; 
       usleep(wait_time); 
       goto read_client; 
      } 
     } 
     goto exit_thread; 

    } else if(result > -1){ 
     bytes_read += result; 
     goto read_client; 
    } 
    respond_request: 

    /* respond stuff start */ 

    /* respond stuff end */ 

    goto read_client; 

    exit_thread: 

下面是涉及创建插座

temp->socket_descriptor = socket(AF_INET, SOCK_STREAM, 0); 

temp->server_address.sin_family = AF_INET; 
temp->server_address.sin_addr.s_addr = INADDR_ANY; 
temp->server_address.sin_port = htons(* temp->port_number); 

if(bind(temp->socket_descriptor, 
      (struct sockaddr *) &temp->server_address, 
      sizeof(temp->server_address)) < 0) .. 

listen(temp->socket_descriptor, 10); 

wait_for_client: 

new_socket = accept(temp->socket_descriptor, 
        (struct sockaddr *) &client_address, 
        &address_length); 

我知道我可能会问太多的代码。如果有人知道一个好的调试工具,我可能会知道这一点,我也非常感谢。如果有人提出了一个调试工具来帮助我解决问题,我也会认为这是一个答案。

编辑:写入和读取功能现在在循环中,但问题仍在发生。

+1

您是否使用wireshark或tcpdump来验证浏览器提供了三个请求?如果是这样,你需要弄清楚你的服务器“跳过”的三个请求中的哪一个。要验证事务,您必须将获取的文件与源文件进行比较。此外,您需要验证响应标题是您期望的响应标题。 – jxh

+0

我刚刚下载了tcpdump,仍在学习如何使用它。 – tay10r

+0

是的,我确实在tcp转储中看到了三个请求。我仍然不知道为什么我没有得到数据,但现在我知道我应该得到请求 – tay10r

回答

2

如果您只是在学习如何使用数据包捕获进行调试,也许wireshark更容易入门。它提供了一个图形用户界面,可以轻松定义简单的规则并直观地检查捕获。它的味道当然是一个问题,所以只是一个建议。

至于代码,很难说这个问题可能是什么,因为它不是SSCCE。我有一些意见,虽然,

  1. 如果你想你释放后,检查之类的东西if(filename),然后filename = NULL;
  2. 如果要将缓冲区清零,请将其设置为memset或循环遍历整个大小。 for(; header_buffer[ i ]; i++) header_buffer[ i ] = 0;的测试看起来很危险。
  3. 准备从一个返回0的套接字读取和写入,除了< 0.
  4. 做你的写入循环。

您的阅读循环是否有完整的请求,或者直到它有更多的0字节?看起来像后者,这是不对的。

编辑,添加以下文字: 代码的例子还不是很完整的(这里是写FEX?),所以很难猜测确切的问题。然而,有几个相当致命的缺陷。

  1. 测试errno不应该像现在这样完成,if(errno & (EWOULDBLOCK | EAGAIN))。在Linux上,你可以测试(errno == EWOULDBLOCK),因为EAGAIN和EWOULDBLOCK是相同的。在不同的系统上,使用||进行两个测试它们之间。如果errno是fex ECONNRESET,那么当前的代码返回非零值(在Linux上)。

  2. 现在代码在技术上涵盖了读取返回0,但不是一个特殊情况。读取返回0表示连接正在关闭,您不应再读取套接字。

一个胡乱猜测什么可能是Web服务器的问题(与上述#2)客户端接收第三文件之前断开与服务器保持忙碌循环闭合的插座上。

我建议通过浏览Beejs guide或一些关于系统和套接字编程的书。

+0

感谢您的回答,我修复了您提到的错误,并使我的代码更整洁一些。我仍然没有解决这个问题,但是我下载了Wireshark并且现在正在使用它。 – tay10r

+0

@Taylor我编辑了我的答案以反映您的更改。 – thuovila

+0

我从头开始重写了代码,没有让程序多线程或动态链接(只是为了避免混乱)。正如你所说,我也占了封闭的连接。它现在可以工作,感谢您的全力帮助。 – tay10r