浏览器访问html页面会下载它的问题?

发布于 2022-09-05 22:50:02 字数 5200 浏览 30 评论 0

问题描述:我用C++写了一个简单的Web服务器,但是,在用浏览器访问HTML页面的时候,它会把这个文件的相关内容下载下来。我用telnet来测试端口的时候,是可以按照我代码的意思看到想要的效果。不知道问题可能是出在哪里?
代码如下:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/unistd.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

using namespace std;

const int BUFFSIZE = 1024;
const int MAXLINK = 10; // 未经过处理的连接请求队列可以容纳的最大数目
const int DEFAULT_PORT = 8080;

int makesure_write(int connect_fd, void* buff, int n) {
    int remain_num = n;
    int success_write_num = 0;
    char* buff_current_postition = (char*)buff;

    while (remain_num > 0) {
        success_write_num = write(connect_fd, buff_current_postition, remain_num);
        remain_num -= success_write_num;
        buff_current_postition += success_write_num;
    }

    return n - remain_num;
}

void get_filetype(const char* file_name, char* file_type) {
    if (strstr(file_name, ".html"))
    strcpy(file_type, "text/html");
    else if (strstr(file_name, ".gif"))
    strcpy(file_type, "image/gif");
    else if (strstr(file_name, ".png"))
    strcpy(file_type, "image/png");
    else if (strstr(file_name, ".jpg"))
    strcpy(file_type, "image/jpeg");
    else
    strcpy(file_type, "text/plain");
}

int get_file_size(char* file_name) {
    FILE* fp = fopen(file_name, "r");
    if (!fp) {
        return -1;
    }
    fseek(fp, 0L, SEEK_END); // 移动文件指针到文件的末尾
    int size = ftell(fp); // 获得目前的文件的访问位置,从而间接获得文件的大小
    fclose(fp);

    return size;
}

char* get_file_name (char* buff) {
    char* file_name = buff + 5;
    char *space = strchr(file_name, ' ');
    *space = '\0';
    return file_name;
}
 
void deal_get_http(int connect_fd, char* request_header) {
    char* file_name = get_file_name(request_header);
    int file_size = get_file_size(file_name);
    char file_type[BUFFSIZE];
    get_filetype(file_name, file_type);

    int fd = open(file_name, O_RDONLY);
    void* file_in_mem_addr = mmap(0, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
    close(fd);

    char buff[BUFFSIZE];
    
    sprintf(buff, "HTTP/1.0 200 OK\r\n");
    sprintf(buff, "%sServer: HHTWS Web Server\r\n", buff);
    sprintf(buff, "%sContent-length: %d\r\n", buff, file_size);
    sprintf(buff, "%sContent-type: %s\r\n\r\n", buff, file_type);

    makesure_write(connect_fd, buff, strlen(buff));
    makesure_write(connect_fd, file_in_mem_addr, file_size);

    munmap(file_in_mem_addr, file_size);
}

bool is_get_http(char* buff) {
    if (!strncmp(buff, "GET", 3)) { // 如果是GET请求
        return true;
    }
    else {
        return false;
    }
}

int main(int argc, char const *argv[])
{


    int socket_fd, connect_fd;
    struct sockaddr_in servaddr;
    char buff[BUFFSIZE];

    socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd == -1) {
            cout<<"create socket error"<<endl;
            return -1;
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // IP必须是网络字节序,INADDR_ANY是绑定本机上所有IP
    servaddr.sin_port = htons(DEFAULT_PORT); // 端口号必须是网络字节序
    
    if (bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) {
        cout<<"bind error"<<endl;
        return -1;
    }

    if (listen(socket_fd, MAXLINK) == -1) {
        cout<<"listen error"<<endl;
    }
    
    connect_fd = accept(socket_fd, (struct sockaddr*)NULL, NULL);
    if (connect_fd == -1) {
        cout<<"accept error"<<endl;
    }
    else {
        cout<<"连接成功"<<endl;
    }

    memset(buff, '\0', sizeof(buff));

    recv(connect_fd, buff, BUFFSIZE - 1, 0); // 把请求头(或发送的消息)写入buff中
    send(connect_fd, buff, BUFFSIZE - 1, 0); // 向客户端发送消息(发送buff中的内容)

    if (is_get_http(buff)) {
        cout<<"it is get http"<<endl;
        deal_get_http(connect_fd, buff);
    }

    close(connect_fd); 
    close(socket_fd);

    return 0;
}

以下是测试的一些截图
虚拟机里面的浏览器访问结果如下:

clipboard.png

也就是说它把文件下载下来了。
然后我把我的代码放到阿里云上面跑,然后通过浏览器访问,得到如下结果:

clipboard.png

clipboard.png

从这张图片里可以看出,响应头并没有发送给浏览器。而这样的结果似乎和在虚拟机下面访问有些不同。在虚拟机里的浏览器是可以获得响应头的。

下面是我通过telnet来测试端口的结果:
服务器部分:

clipboard.png

客户端部分:

clipboard.png

从这个结果看下来,感觉返回的信息是写对了。问题好像是出在如何让浏览器来接收这个响应?

我感觉是不是返回响应头给客户端的时候出了问题?

希望前辈可以解答

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七婞 2022-09-12 22:50:02

我在本地测试了一下,完全没问题,浏览器打印出了I am index.

你其实不用写这么麻烦,你可以去看看CGI的功能,就是你想要的,你不需要按照HTTP协议自己全部重新实现,把对接HTTP协议的部分交给CGI就可以了

じ违心 2022-09-12 22:50:02

大哥 你用文件浏览器方式打开 肯定是下载 或者打开源码啊,得部署到服务器 ,比如PHPstudy

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文