【问题标题】:how to send an image in winsock2, using c如何使用c在winsock2中发送图像
【发布时间】:2011-03-16 14:58:55
【问题描述】:

我正在用 c (winsock2) 编写一个非常简单的网络服务器。

我能够返回我的 html 页面的内容。

目前,我正在做的是将文件的内容写入 char* 缓冲区并使用“send()”发送它

虽然当我尝试读取图像(jpg、bmp)时,我无法将字符写入缓冲区,因为某些字符是“null”(0)。

如何发送整个图像文件?

谢谢。

【问题讨论】:

    标签: c windows visual-studio-2010 winsock2


    【解决方案1】:

    您可以将空字符存储在char* 缓冲区中。您只需要使用计数器来记住写入了多少字符,而不是通过计算非空字符的数量来重新计算它(这可以是整数或指向缓冲区中下一个插入点的指针)。

    要发送文件,您需要执行以下操作:

    int sendFile(int sock, const char* filename) {
        FILE* file = fopen(filename, "rb");
        if (file == NULL)
            return -1;
    
        if (fseek(file, 0, SEEK_END) != 0) {
            fclose(file);
            return -1;
        }
    
        off_t size = ftello(file);
        if (fseek(file, 0, SEEK_SET) != 0) {
            fclose(file);
            return -1;
        }
    
        if (SendBinaryFileHeaderAndSize(sock, size) < 0) {
            fclose(file);
            return -1;
        }
    
        char buffer[4096];
        for (;;) {
            size_t read = fread(buffer, 1, sizeof(buffer), file);
            if (read == 0) {
                int retcode = 0;
                if (ferror(file))
                    retcode = -1;
                fclose(file);
                return retcode;
            }
    
            for (size_t sent = 0; sent < read;) {
                int ret = send(sock, buffer + sent, read - sent, 0);
                if (ret < 0) {
                    fclose(file);
                    return -1;
                }
    
                assert(ret <= read - sent);
                sent += ret;
            }
        }
    }
    

    【讨论】:

    • 我如何知道 c 中图像文件的大小?一旦我知道我可以使用 fgetc 从图像中获取内容吗?另外,我想我从 fseek 得到了大小。但是当我在浏览器中打开图像时,浏览器只是一个空白页面。里面什么都没有。
    • 您可以使用fseek(file, O, SEEK_END),或一些特定于平台的代码(lstatGetFileInformationByHandle,...)来获取文件的大小。您还需要检查您是否按照 HTTP 协议向您的客户端发送了正确的标头(大小、内容类型...)(您可以使用另一个网络服务器来检查它在尝试访问二进制文件时发送的内容) .
    • 我似乎能够读取该文件。虽然当我打开它。我可以下载该文件,但它说损坏。 fgetc 是否返回签名的 char ? winsock.send 是否允许传输无符号字符?
    • 对于二进制文件,您可能应该使用fread 读取它的整个块,而不是使用fgetc 逐字节读取它(这将更有效)。 send 函数不解释缓冲区的内容,它按原样传输,fgetc 返回一个int(以便能够区分 EOF 和简单字符)。因此,在使用该值时必须小心,因为 char 已扩展到 int 并且符号可能已被传播。
    • 非常感谢,是的,一个非常相似的代码对我有用。基本上我现在正在做的是传输 3096 字节的数据,直到发送完所有字节。谢谢。
    【解决方案2】:

    您需要了解 send() 和 fread() 的工作原理。缓冲区中的 0 对 send 或 fread 来说不是问题 - 它们不会将缓冲区解释为以 null 结尾的字符串。

    【讨论】:

      【解决方案3】:

      根据您将图像加载到网络服务器的方式,您需要使用Winsock:TransmitPacketsWinsock:TransmitFile,还需要将图像包装在适当的 HTTP 标头中

      请注意,这些是特定于 MS 的扩展。

      另见c++ - Bitmap transfer using winsock getdibits and setdibits

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多