首页 新闻 搜索 专区 学院

C语言实现简单 http server ,浏览器不能识别返回的 http头

0
悬赏园豆:30 [已解决问题] 解决于 2016-10-28 09:09
复制代码
  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/socket.h>
  4 #include <netinet/in.h>
  5 #include <arpa/inet.h>
  6 #include <string.h>
  7 #include <unistd.h>
  8 #include <stdlib.h>
  9 #include <errno.h>
 10 #include <fcntl.h>
 11 #include <sys/sendfile.h>
 12 #include <sys/stat.h>
 13 
 14 
 15 
 16 
 17 
270 int main(int argc, char *argv[])
271 {
272     int server_sockfd;//服务器端套接字
273     int client_sockfd;//客户端套接字
274     int len,pid;
275     struct sockaddr_in my_addr;   //服务器网络地址结构体
276     struct sockaddr_in remote_addr; //客户端网络地址结构体
277     int sin_size;
278     char buf[BUFSIZ];  //数据传送的缓冲区
279     memset(&my_addr, 0, sizeof(my_addr)); //数据初始化--清零
280     my_addr.sin_family = AF_INET; //设置为IP通信
281     my_addr.sin_addr.s_addr = INADDR_ANY; //服务器IP地址--允许连接到所有本地地址上
282     my_addr.sin_port = htons(8000); //服务器端口号
283 
284     /*创建服务器端套接字--IPv4协议,面向连接通信,TCP协议*/
285     if((server_sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
286     {
287         perror("socket");
288         return 1;
289     }
290 
291     /*将套接字绑定到服务器的网络地址上*/
292     if (bind(server_sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) < 0)
293     {
294         perror("bind");
295         return 1;
296     }
297 
298     /*监听连接请求--监听队列长度为5*/
299     listen(server_sockfd, 5);
300 
301     sin_size = sizeof(struct sockaddr_in);
302 
349     
350     while (1)
351     {
352         client_sockfd = accept(server_sockfd, (struct sockaddr *) &remote_addr, &sin_size);
353         // send(client_sockfd, "Welcome to my server\n", 21, 0);
354         if (client_sockfd < 0)
355             error("ERROR on accept");
356         pid = fork();
357         if (pid < 0)
358             error("ERROR on fork");
359         if (pid == 0)
360         {
361             close(server_sockfd);
362             char html[] = "\r\n\
363     HTTP/1.1 200 OK \r\n \r\n\
364 \
365     <html><head></head><body><h1>HTTP Server</h1></body></html>\
366             ";
367             recv(client_sockfd, buf, BUFSIZ, 0);
368             printf("%s\n", buf);
369             send(client_sockfd, html, strlen(html), 0);
370             // connection(client_sockfd);
371             // html_handle(client_sockfd);
372             close(client_sockfd);
373             exit(0);
374         }
375         else
376             close(client_sockfd);
377     } /* end of while */
378     close(server_sockfd);
379     return 0;
380 }
复制代码

上面是我实现的一个  http server   测试了n久   用浏览器访问总是  直接把http 头  显示到页面上了 ,  浏览器不能识别的这个头

浏览器访问结果:

 

之后我用python 又实现了一次,就没有问题。

 

有哪位大神知道这是怎么回事?

 

 

问题补充:

上面的问题已经解决:

把字符串

"HTTP/1.0 200 OK\r\n\r\n<!DOCTYPE html><html><head></head><body><h1>HTTP Server</h1></body></html>"

分两次发送就OK了

如:

1 send_new(client_sockfd,"HTTP/1.0 200 OK\r\n\r\n");
2  
3 send_new(client_sockfd,"<!DOCTYPE html><html><head></head><body><h1>HTTP Server</h1></body></html>");
4             

 

但是不知道原理是为什么,希望知道的大神能给解释一下

_Arnold的主页 _Arnold | 小虾三级 | 园豆:635
提问于:2016-10-26 15:03
< >
分享
最佳答案
0

send_new(client_sockfd,"HTTP/1.0 200 OK\r\n\r\n");

send_new(client_sockfd,"<!DOCTYPE html><html><head></head><body><h1>HTTP Server</h1></body></html>");

 

_Arnold | 小虾三级 |园豆:635 | 2016-10-28 09:06
其他回答(4)
0

查看网页源代码

吴瑞祥 | 园豆:28851 (高人七级) | 2016-10-26 15:14

感谢回复,网页源代码已经很清楚了,是我自己写的字符串呀。

支持(0) 反对(0) _Arnold | 园豆:635 (小虾三级) | 2016-10-26 15:41
0

文档格式是否正确(要让浏览器以html解析,看起来就没写文档类型)?

代码中的编码是否正确?(比如都是string,c是默认asc的,比如其他ide出来的可能是utf8)

文档是否编码处理?([url encode],html encode)

花飘水流兮 | 园豆:12031 (专家六级) | 2016-10-26 15:24

1、应该跟文档类型没有关系,因为python这边返回的一样的字符串  ,就可以被浏览器解析

<html><head></head><body><h1>HTTP Server</h1></body></html>

2、编码问题我试着这样声明字符串 :

 char html[] = u8"..."  

    不知道对不对(之前接触c的机会比较少),而且如果能在浏览器中显示正确字符应该就不是编码的问题吧

 

支持(0) 反对(0) _Arnold | 园豆:635 (小虾三级) | 2016-10-26 15:40

@xiaoxiao刀: 

 char html[] = u8"..."  

 不是这个意思的编码,比如MFC中有LChar、TChar...编码是不一样的,是程序本身的字符串编码。然后才是http 协议内的编码(url编码,html编码)。

支持(0) 反对(0) 花飘水流兮 | 园豆:12031 (专家六级) | 2016-10-26 17:44

@xiaoxiao刀: 浏览器比较高层,这种低级的测试,你可以直接用16进制打出来就清楚了。一眼就对比出来了。

支持(0) 反对(0) 花飘水流兮 | 园豆:12031 (专家六级) | 2016-10-26 17:47
0

头前面不应该有空行吧,换行表示正文开始了。

长蘑菇星人 | 园豆:1832 (小虾三级) | 2016-10-26 15:51

 嗯  我把前面的换行去掉之后   浏览器就干脆获取不到信息了   

支持(0) 反对(0) _Arnold | 园豆:635 (小虾三级) | 2016-10-26 15:55

@xiaoxiao刀: 2333

因为你HTTP版本大于1.0,所以要告诉浏览器,你内容格式,和内容长度,等。

建议看一下HTTP协议。

支持(0) 反对(0) 长蘑菇星人 | 园豆:1832 (小虾三级) | 2016-10-26 16:01

@长蘑菇星人: 

我明白你的意思 ,可是有个问题,这是我用python实现的  http server

import os
import socket
import time

SERVER_ADDRESS = (HOST, PORT) = '', 8888
REQUEST_QUEUE_SIZE = 5

def handle_request(client_connection):
    request = client_connection.recv(1024)
    print(
        'Child PID: {pid}. Parent PID {ppid}'.format(
            pid=os.getpid(),
            ppid=os.getppid(),
        )
    )
    print(request.decode())
    http_response = b"""\
    HTTP/1.1 200 OK \n \n
    <html><head></head><body><h1>HTTP Server</h1></body></html>
    """
    client_connection.sendall(http_response)
    # time.sleep(60)

def serve_forever():
    listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    listen_socket.bind(SERVER_ADDRESS)
    listen_socket.listen(REQUEST_QUEUE_SIZE)
    print('Serving HTTP on port {port} ...'.format(port=PORT))
    print('Parent PID (PPID): {pid}\n'.format(pid=os.getpid()))
    while True:
        client_connection, client_address = listen_socket.accept()
        pid = os.fork()
        if pid == 0:  # child
            listen_socket.close()  # close child copy
            handle_request(client_connection)
            client_connection.close()
            os._exit(0)  # child exits here
        else:  # parent
            client_connection.close()  # close parent copy and loop over

if __name__ == '__main__':
    serve_forever()

返回的字符串是一样的,最后结果:

支持(0) 反对(0) _Arnold | 园豆:635 (小虾三级) | 2016-10-26 16:07

@长蘑菇星人: 

感觉应该是二楼说的,c语言的问题,但具体哪里错了 还不清楚

支持(0) 反对(0) _Arnold | 园豆:635 (小虾三级) | 2016-10-26 16:13
0

http协议还没搞清楚哦。快去看看

收获园豆:30
czd890 | 园豆:9531 (大侠五级) | 2016-10-26 16:45

看过了  也按照http的格式改了很多次     最后没效果才放上来的

支持(0) 反对(0) _Arnold | 园豆:635 (小虾三级) | 2016-10-26 16:55

@xiaoxiao刀: http://phl.iteye.com/blog/1876867

吧该加的header 头加上。没有contentlength 不知道解析。第一行不要有任何字符换行,空格什么的

支持(0) 反对(0) czd890 | 园豆:9531 (大侠五级) | 2016-10-26 17:12

@calvinK: 

好的  我试试。   但是为什么python 返回的同样的数据却行呢?

支持(0) 反对(0) _Arnold | 园豆:635 (小虾三级) | 2016-10-26 17:22

@xiaoxiao刀: tcp抓包看看呗

支持(0) 反对(0) czd890 | 园豆:9531 (大侠五级) | 2016-10-26 17:26

@calvinK: 

还是老样子  不显示任何数据  

下面是我telnet  返回的数据   数据格式看着没什么问题 

支持(0) 反对(0) _Arnold | 园豆:635 (小虾三级) | 2016-10-26 17:31

@xiaoxiao刀: 看着没问题,浏览器F12 response有东西么。没有就还是解析有问题。可以c和py的tcp抓包看看

支持(0) 反对(0) czd890 | 园豆:9531 (大侠五级) | 2016-10-26 17:37

length 有145吗?我数了一下,貌似不够。。。。

支持(0) 反对(0) czd890 | 园豆:9531 (大侠五级) | 2016-10-26 17:39

@calvinK: 

有空格换行符之类的 都算进去

支持(0) 反对(0) _Arnold | 园豆:635 (小虾三级) | 2016-10-27 08:14

@xiaoxiao刀: content-length 只是<html>....这一部分哦

支持(0) 反对(0) czd890 | 园豆:9531 (大侠五级) | 2016-10-27 15:20

@calvinK: 

问题已经解决跟响应头的设置没有关系

支持(0) 反对(0) _Arnold | 园豆:635 (小虾三级) | 2016-10-27 15:55
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册