【问题标题】:c- HTTP server on sockets doesn't display image correctc- 套接字上的 HTTP 服务器不正确显示图像
【发布时间】:2018-05-06 09:26:14
【问题描述】:

我的任务是实现一个简单的 HTTP 服务器。我尝试打开一个通过 HTTP 下载的站点。我的服务器可以正确显示 html、css 和 js 文件,但无法显示图像(png、jpg)。我用 Wireshark 记录了这些响应数据包:

HTTP/1.1 200 OK
Connection: keep-alive
Transfer-Encoding: chunked
.PNG
.

这也是我读取请求并向客户端发送响应的函数。

static int serve_request(int sock, struct conf_arg *arg, char version[])
{
    FILE *html = NULL;
    char buf[MAX_MSG];
    const unsigned chunk = (unsigned)CHUNK_SIZE;
    char *pbuf = NULL;
    char tempbuf[CHUNK_SIZE + 3];
    size_t len;

    strcpy(buf, arg->root);
    if(buf[strlen(buf) - 1] == '/')
        strcat(buf, arg->defdoc);
    html = fopen(buf, "rb");
    if (!html) {
        not_found(sock, version);
        return -1;
    }
    good_responce(sock, version);
    do {
        if (fgets(buf, sizeof(buf), html) == NULL)
            break;
        pbuf = buf;
        while ((len = strlen(pbuf)) != 0) {
            if (len < chunk) {
                //printf("LEN:%d\n", (int)len);
                sprintf(tempbuf, "%x\r\n", (int)len);
                write(sock, tempbuf, strlen(tempbuf));
                write(sock, pbuf, strlen(pbuf));
                //printf("%s", pbuf);
                pbuf += len;
                write(sock, "\r\n", 2);
            } else {
                sprintf(tempbuf, "%x\r\n", (int)chunk);
                write(sock, tempbuf, strlen(tempbuf));
                //strncpy(tempbuf, pbuf, chunk);
                //printf("%d\n%s\n", (int)chunk, tempbuf);
                write(sock, pbuf, chunk);
                pbuf += chunk;
                write(sock, "\r\n", 2);
            }
        }
    } while (!feof(html));
    strcpy(tempbuf, "0\r\n\r\n");
    write(sock, tempbuf, strlen(tempbuf));
    fclose(html);
    return 0;
}

我不知道问题出在哪里,所以希望你能帮助我。
UPD:我将打开模式更改为 rb,但没有帮助。我在 Wireshark 中得到相同的输出。

【问题讨论】:

  • 您正在以文本模式打开文件,这可能是问题所在。
  • 我应该使用什么模式?
  • 二进制模式。这很可能是问题
  • 二进制,当然?
  • 是的,一般来说,任何带有 strlen() 的网络代码都会被破坏。

标签: c linux sockets server


【解决方案1】:

您必须以二进制模式打开图像文件。

您必须使用二进制文件读取操作。您现在读取的缓冲区没有strlen,因为它是二进制的;缓冲区的大小由read 操作报告。

写入套接字也将是二进制的,因此 write(sock, pbuf, strlen(pbuf)); 将不起作用,而是使用 write(sock, pbuf, n_bytes);n_bytes 要发送的缓冲区中的字节数。

这可能意味着重新编写代码以使用所有二进制操作。将 css 和 html 文件视为二进制文件和将其视为文本一样容易传输。如果您将代码更改为全二进制,则任何类型的文件都不会出现问题。

【讨论】:

    【解决方案2】:

    很可能您没有以二进制模式打开图像文件:

     {
       FILE *fp;
       char buffer[512];
    
       fp = fopen("image_file.png", "rb");
       while...
    

    如果你不指定二进制模式,你的二进制数据会发生奇怪的事情。

    此外,您正在使用fgets,其本质上将与您尝试对二进制数据执行的操作不兼容。你应该考虑使用fread()

    【讨论】:

    • 啊...更新答案
    • 在你的情况下,我希望每个元素都是一个字节。您将尝试读取与读取缓冲区大小匹配的字节数。
    猜你喜欢
    • 1970-01-01
    • 2014-01-16
    • 2021-12-13
    • 2014-02-21
    • 1970-01-01
    • 2015-06-06
    • 2014-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多