我有一个用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;
}
答案 0 :(得分:3)
你要改变的第一件事是while (!fileHandle.eof())
循环,因为它不会像你期望的那样工作,实际上它会迭代一次太多,因为eof
标志不是设置,直到您尝试从文件末尾读取之后。相反,例如, while (fileHandle.read(...))
。
你应该做的第二件事是检查从文件中实际读取了多少字节,并且只发送了那么多的字节。
最后,您阅读了二进制数据,而不是文本,因此您无法对从该文件中读取的数据使用strlen
。
对二进制文件问题的一些解释:正如您应该知道的那样,C样式字符串(您使用strlen
获取长度的字符串)以零字符'\0'
终止(简而言之,一个零字节)。随机二进制数据可以在其中的任何位置包含许多零字节,并且它是一个有效字节,并没有任何特殊含义。
当您使用strlen
获取二进制数据的长度时,有两个可能的问题:
数据中间有一个零字节。这将导致strlen
提前终止并返回错误的长度。
数据中有 no 零字节。这将导致strlen
超出缓冲区的末尾以查找零字节,从而导致未定义的行为。