【问题标题】:How to send HTML page from C web-server to web-browser如何将 HTML 页面从 C 网络服务器发送到网络浏览器
【发布时间】:2018-05-13 23:43:16
【问题描述】:

我已经用 C 语言实现了基本的 Web 服务器,它服务于来自客户端的 GET 请求。问题是它不发送 HTML 页面。

while(1){
        if((temp_sock[id] = accept(sockfd, (t_sockaddr*)address, &address_size))==-1){
            perror("Accepting Failure: ");
            pthread_mutex_lock(&lock);
            fprintf(logfile, "Accepting error: %d\n", localfd);
            pthread_mutex_unlock(&lock);
            exit(1);
        }
        else{
            pthread_mutex_lock(&lock);
            fprintf(logfile, "\nAccepting Success");
            pthread_mutex_unlock(&lock);
        }

        if (temp_sock[id]> 0){
            pthread_mutex_lock(&lock);
            fprintf(logfile, "\nClient is connected");
            pthread_mutex_unlock(&lock);
        }

        recv(temp_sock[id] , buf, buffsize, 0);

        pthread_mutex_lock(&lock);
        fprintf(logfile, "\nyou recieved : %s\n ", buf);
        pthread_mutex_unlock(&lock);

        if((resource=analyze(buf))==NULL){ /*analyze - implements basic security and searches files on a disc*/
            printf("\nres is NULL");
            write(temp_sock[id], "HTTP/1.1 200 OK\n", 16);
            write(temp_sock[id], "Content-length: 50\n", 19);
            write(temp_sock[id], "Content-Type: text/html\n\n", 25);
            write(temp_sock[id], "<html><body><H1>404 Not Found</H1></body></html>", 50); 
        }
        else{
            while(fgets(message, 150, resource)!=NULL){
                write(temp_sock[id], "HTTP/1.1 200 OK\n", 16);
                write(temp_sock[id], "Content-length: 151\n", 19);
                write(temp_sock[id], "Content-Type: text/html\n\n", 25);
                write(temp_sock[id], message, 151); //here problems start
            }
        fclose(resource);
        }
        close(temp_sock[id]);
    }
}

这只是接受一个线程的循环,我没有发布整个代码,因为在我想要发送包含多行文本的页面(例如维基百科文章)之后一切正常读取文件网络服务器刚刚停止。但是如果文件只包含

<html><body><H1>Hello! How are you?</H1></body></html>

服务器以正确的方式发送它。 提前致谢。

【问题讨论】:

    标签: c http tcp server


    【解决方案1】:

    您的代码存在多个问题,但最严重的问题在这里:

    while(fgets(message, 150, resource)!=NULL){
        write(temp_sock[id], "HTTP/1.1 200 OK\n", 16);
        write(temp_sock[id], "Content-length: 151\n", 19);
        write(temp_sock[id], "Content-Type: text/html\n\n", 25);
        write(temp_sock[id], message, 151); //here problems start
    }
    
    1. fgets() 仅适用于字符串。读取二进制数据(如图像)时,它的行为会不正确。请改用fread();您需要对参数重新排序。

    2. HTTP 中的响应行必须以\r\n 终止,而不仅仅是\n。 (这不会导致您的问题,但无论如何您都应该解决它。)

    3. 您发送的 151 的 Content-Length 是伪造的。检查文件的实际大小(例如,使用fstat())并发送它,或者根本不发送 Content-Length。这不是强制性的。

    4. 您的代码写入的字节数多于读取的字节数。保存来自fgets() 的返回值并将其传递给write()

    5. 您的代码未检查来自 write() 的返回值。假设write() 将始终写入您提供给它的所有数据是不安全的——就像read(),它可能执行部分写入,或完全失败。

    6. 您的代码正在为其读取的每个数据块发送一组新的 HTTP 标头。将该代码移出循环。

    【讨论】:

    • 好的,谢谢,但是如果我有一个页面,里面有一篇文章,包含大约 500 行,我应该分配然后一次发送所有内容还是将其分成几部分?
    • @TeamBeam 这取决于你。但是,如果您确实决定将其拆分为多个写入,请使用更大的缓冲区大小 - 大约 64 KB,而不是 150 字节。
    • @TeamBeam,您在标头中告诉客户端文件的整个大小(您只发送一次),然后您以对您的服务器有意义的任何块大小读取和传输数据。客户端不需要知道您将 1MB 文件读取为 500 个 2KB 块,他们所看到的只是 1MB 到达的流。
    • @lockcmpxchg8b 哦,现在我明白了,谢谢你和OP。服务器工作。我唯一要补充的是 fgets 返回一个指针 char *fgets(char *str, int n, FILE *stream)- 声明
    • @TeamBeam:你仍然不应该使用fgets(),而是使用fread()
    【解决方案2】:

    我认为主要问题是您多次发送 HTTP 标头。除了@duskwuff 提到的问题,你应该改变你的循环

    write(temp_sock[id], "HTTP/1.1 200 OK\n", 16);
    write(temp_sock[id], "Content-length: 151\n", 19); ///here still is a problem mentioned above
    write(temp_sock[id], "Content-Type: text/html\n\n", 25);
    while((currLen=fgets(message, 150, resource))!=0){
    
        write(temp_sock[id], message, currLen);
    }
    

    【讨论】:

    • 这是我提到的问题之一。请参阅最后一个要点。
    • 对不起,你是对的。不知道为什么之前没看到:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-31
    • 1970-01-01
    • 1970-01-01
    • 2011-11-11
    • 2020-07-30
    • 1970-01-01
    相关资源
    最近更新 更多