简体   繁体   English

如何格式化HTTP响应

[英]How to format the HTTP response

I have written a socket program in C. I used this program as a chat server/client using TCP. 我用C语言编写了一个套接字程序。我将此程序用作使用TCP的聊天服务器/客户端。 I tried to change the chat server to use it as a HTTP server by changing the port to 80. I referred to the HTTP request/response format in http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Example_session , and made my program to reply with sample response. 我尝试通过将端口更改为80来更改聊天服务器以将其用作HTTP服务器。我在http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Example_session中引用了HTTP请求/响应格式,程序以示例响应进行回复。 I tried the url 我尝试了网址

http://127.0.0.1/ 

in browser. 在浏览器中。 My program read the request and replied with response. 我的程序读取了请求并回复了响应。 At first, I used google-chrome. 最初,我使用google-chrome。 Chrome didn't load the page correctly until i added the correct data length in Content-Length header. 在我在Content-Length标头中添加正确的数据长度之前,Chrome浏览器无法正确加载页面。 After setting content length header, chrome loaded the page correctly. 设置内容长度标题后,chrome正确加载了页面。 But, firefox doesn't load the page. 但是,firefox不会加载页面。 Firefox doesn't showed any errors, but still loading the page like it is still waiting for some data. Firefox没有显示任何错误,但仍在加载页面,就像它仍在等待一些数据一样。 Only When i stop the server or close the socket, complete page is loaded. 仅当我停止服务器或关闭套接字时,才会加载完整页面。 I tried to follow rfc2616 http://tools.ietf.org/html/rfc2616 , and made the response exactly , but the still the results are same. 我尝试遵循rfc2616 http://tools.ietf.org/html/rfc2616 ,并做出了准确的响应,但结果仍然相同。

Request: 请求:

GET / HTTP/1.1\\r\\nHost: 127.0.0.1:8080\\r\\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:33.0) Gecko/20100101 Firefox/33.0\\r\\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9, / ;q=0.8\\r\\nAccept-Language: en-US,en;q=0.5\\r\\nAccept-Encoding: gzip, deflate\\r\\nConnection: keep-alive\\r\\n\\r\\n GET / HTTP / 1.1 \\ r \\ n主机:127.0.0.1:8080\\r\\n用户代理:Mozilla / 5.0(X11; Ubuntu; Linux x86_64; rv:33.0)Gecko / 20100101 Firefox / 33.0 \\ r \\ n接受:text / html,application / xhtml + xml,application / xml; q = 0.9, / ; q = 0.8 \\ r \\ nAccept-Language:en-US,en; q = 0.5 \\ r \\ nAccept-Encoding:gzip,deflate \\ r \\ nConnection:保持活动状态\\ r \\ n \\ r \\ n

For the above request, my program write to the socket with following response & content. 对于以上请求,我的程序将以下响应和内容写入套接字。

Response: 响应:

HTTP/1.1 200 OK\\r\\nCache-Control : no-cache, private\\r\\nContent-Length : 107\\r\\nDate : Mon, 24 Nov 2014 10:21:21 GMT\\r\\n\\r\\n HTTP / 1.1 200 OK \\ r \\ n缓存控制:无缓存,私有\\ r \\ n内容长度:107 \\ r \\ n日期:2014年11月24日星期一10:21:21 GMT \\ r \\ n \\ r \\ n

Content: 内容:

<html><head><title></title></head><body>TIME : 1416824843 <br>DATE: Mon Nov 24 15:57:23 2014 </body></html>

This response is loading in Chrome, but not in firefox. 此响应正在Chrome中加载,但不会在Firefox中加载。 Chrome is loading the page instantly whereas firefox is waiting for data. Chrome正在立即加载页面,而Firefox正在等待数据。 Note that the data length 107 is specified in the header. 注意,在标题中指定数据长度107。 I donot have any addons enabled in firefox. 我没有在Firefox中启用任何插件。 My firefox version is in the request. 我的Firefox版本在请求中。 Chrome version: Version 38.0.2125.111 (64-bit). Chrome版本:版本38.0.2125.111(64位)。

Code: 码:

void *socket_read(void *args)
{
    int socket,*s,length;
    char buf[1024];
    s=(int *)args;
    socket=*s;
    while(1){
        buf[0]='\0';
        length=read(socket,buf,1024);
        if(length==0)
            break;
        else if(length==-1){
            perror("Read");
            return;
        }
        else{
            printf("Request: %s\n",buf);
            send_response(socket);
        }       
    }
    printf("End of read thread [%d]\n",socket);
}
int start_accept(int port)
{
    int socket,csocket;
    pthread_t thread;
    struct sockaddr_in client;
    socklen_t addrlen=sizeof(client);
    pthread_attr_t attr;
    socket=create_socket(port);
    while(1){
        if((csocket=accept(socket,(struct sockaddr *)&client,&addrlen))==-1)
        {   
            perror("Accept");
            break;
        }
        pthread_attr_init(&attr);
        if(0!=pthread_create(&thread,&attr,socket_read,&csocket))
        {
            perror("Read thread");
            return;
        }
        usleep(10000);
    }
}
void send_response(int socket)
{
    char buf1[1024];
    int content_length;
    char buf2[1024]="<html><head><title></title></head><body>TIME : 1416824843 <br>DATE: Mon Nov 24 15:57:23 2014 </body></html>";
    content_length=strlen(buf2);
    sprintf(buf1,"HTTP/1.1 200 OK\r\nCache-Control : no-cache, private\r\nContent-Length : %d\r\nDate : Mon, 24 Nov 2014 12:03:43 GMT\r\n\r\n",content_length);
    printf("Written: %d \n",write(socket,buf1,strlen(buf1)));
    fflush(stdout);
    printf("Written: %d \n",write(socket,buf2,content_length));
    fflush(stdout);
}

I have found the problem. 我发现了问题。 The Response is incorrect. 响应不正确。 There should not be any spaces between the header field name and colon(':'). 标头字段名称和冒号(':')之间不应有任何空格。 Found this in http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 . http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2中找到了此内容。

My correct response is 我的正确回答是

HTTP/1.1 200 OK\r\nCache-Control: no-cache, private\r\nContent-Length: 107\r\nDate: Mon, 24 Nov 2014 10:21:21 GMT\r\n\r\n

I have put a space between 'Content-Length' and ':' . 我在'Content-Length'和':'之间放置了一个空格。 That's the reason Firefox ignored the content length header and reading the socket. 这就是Firefox忽略内容长度标头并读取套接字的原因。 Chrome accepted the header fields with spaces, so the problem doesn't occurred in chrome. Chrome接受标头字段带有空格,因此在chrome中不会发生此问题。

After removing the space, program works fine. 删除空间后,程序运行正常。

It actually loads the page. 它实际上加载页面。 If you add content-type header you will see the HTML page (Content-Type: text/html; charset=UTF-8\\r\\n) 如果添加内容类型标题,您将看到HTML页面(内容类型:text / html; charset = UTF-8 \\ r \\ n)

Anyway, both in Chrome and in Firefox you will see the connections never stops because the server doesn't close the socket. 无论如何,在Chrome和Firefox中,您都将看到连接永远不会停止,因为服务器没有关闭套接字。 If you closed csocket, you would see the HTML page in both browsers but as you said it should be a persistent connection. 如果关闭csocket,则在两个浏览器中都将看到HTML页面,但是正如您所说的,它应该是一个持久连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM