如何通过linux socket发送图像数据

时间:2015-09-06 17:24:40

标签: c++ linux sockets

我有一个用C ++编写的相对简单的Web服务器。它适用于提供文本/ html页面,但它的编写方式似乎无法发送二进制数据,我真的需要能够发送图像。

我一直在搜索和搜索,但无法找到特定于这个问题的答案,这个问题是用真正的C ++编写的(fstream而不是使用文件指针等),虽然这种事情必然是低级的,可能需要处理C样式数组中的字节我希望代码尽可能为C ++。

我尝试了一些方法,这就是我目前的方法:

int sendFile(const Server* serv, const ssocks::Response& response, int fd)
{
// some other stuff to do with headers etc. ........ then:

    // open file
    std::ifstream fileHandle;
    fileHandle.open(serv->mBase + WWW_D + resource.c_str(), std::ios::binary);

    if(!fileHandle.is_open())
    {            
        // error handling code
        return -1;
    }

    // send file
    ssize_t buffer_size = 2048;
    char buffer[buffer_size];

    while(!fileHandle.eof())
    {
        fileHandle.read(buffer, buffer_size);

        status = serv->mSock.doSend(buffer, fd);
        if (status == -1)
        {
            std::cerr << "Error: socket error, sending file\n";
            return -1;
        }
    }
    return 0
}

然后在其他地方:

int TcpSocket::doSend(const char* message, int fd) const
{
    if (fd == 0)
    {
         fd = mFiledes;
    }

    ssize_t bytesSent = send(fd, message, strlen(message), 0);
    if (bytesSent < 1)
    {
        return -1;
    }

    return 0;
}

正如我所说,问题在于,当客户请求图像时,它不会起作用。我进入std :: cerr&#34;错误:套接字错误发送文件&#34;

编辑:我使用了我接受的答案中的建议。为了完整性并帮助那些发现这篇文章,我也发布了最终的工作代码。

对于发送我决定使用std :: vector而不是char数组。主要是因为我觉得它是一种更加C ++的方法,它清楚地表明数据不是字符串。这可能不是必要的,而是品味问题。然后,我计算了为流读取的字节数,并将其传递给send函数,如下所示:

// send file
std::vector<char> buffer(SEND_BUFFER);
while(!fileHandle.eof())
{
    fileHandle.read(&buffer[0], SEND_BUFFER);
    status = serv->mSock.doSend(&buffer[0], fd, fileHandle.gcount());
    if (status == -1)
    {
        std::cerr << "Error: socket error, sending file\n";
        return -1;
    }
}

然后实际的发送功能改编如下:

int TcpSocket::doSend(const char* message, int fd, size_t size) const
{
    if (fd == 0)
    {
        fd = mFiledes;
    }

    ssize_t bytesSent = send(fd, message, size, 0);
    if (bytesSent < 1)
    {
        return -1;
    }

    return 0;
}

1 个答案:

答案 0 :(得分:3)

你要改变的第一件事是while (!fileHandle.eof())循环,因为它不会像你期望的那样工作,实际上它会迭代一次太多,因为eof标志不是设置,直到您尝试从文件末尾读取之后。相反,例如, while (fileHandle.read(...))

你应该做的第二件事是检查从文件中实际读取了多少字节,并且只发送了那么多的字节。

最后,您阅读了二进制数据,而不是文本,因此您无法对从该文件中读取的数据使用strlen

对二进制文件问题的一些解释:正如您应该知道的那样,C样式字符串(您使用strlen获取长度的字符串)以零字符'\0'终止(简而言之,一个零字节)。随机二进制数据可以在其中的任何位置包含许多零字节,并且它是一个有效字节,并没有任何特殊含义。

当您使用strlen获取二进制数据的长度时,有两个可能的问题:

  1. 数据中间有一个零字节。这将导致strlen提前终止并返回错误的长度。

  2. 数据中有 no 零字节。这将导致strlen超出缓冲区的末尾以查找零字节,从而导致未定义的行为