【发布时间】:2011-03-16 14:58:55
【问题描述】:
我正在用 c (winsock2) 编写一个非常简单的网络服务器。
我能够返回我的 html 页面的内容。
目前,我正在做的是将文件的内容写入 char* 缓冲区并使用“send()”发送它
虽然当我尝试读取图像(jpg、bmp)时,我无法将字符写入缓冲区,因为某些字符是“null”(0)。
如何发送整个图像文件?
谢谢。
【问题讨论】:
标签: c windows visual-studio-2010 winsock2
我正在用 c (winsock2) 编写一个非常简单的网络服务器。
我能够返回我的 html 页面的内容。
目前,我正在做的是将文件的内容写入 char* 缓冲区并使用“send()”发送它
虽然当我尝试读取图像(jpg、bmp)时,我无法将字符写入缓冲区,因为某些字符是“null”(0)。
如何发送整个图像文件?
谢谢。
【问题讨论】:
标签: c windows visual-studio-2010 winsock2
您可以将空字符存储在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;
}
}
}
【讨论】:
fseek(file, O, SEEK_END),或一些特定于平台的代码(lstat,GetFileInformationByHandle,...)来获取文件的大小。您还需要检查您是否按照 HTTP 协议向您的客户端发送了正确的标头(大小、内容类型...)(您可以使用另一个网络服务器来检查它在尝试访问二进制文件时发送的内容) .
fread 读取它的整个块,而不是使用fgetc 逐字节读取它(这将更有效)。 send 函数不解释缓冲区的内容,它按原样传输,fgetc 返回一个int(以便能够区分 EOF 和简单字符)。因此,在使用该值时必须小心,因为 char 已扩展到 int 并且符号可能已被传播。
您需要了解 send() 和 fread() 的工作原理。缓冲区中的 0 对 send 或 fread 来说不是问题 - 它们不会将缓冲区解释为以 null 结尾的字符串。
【讨论】:
根据您将图像加载到网络服务器的方式,您需要使用Winsock:TransmitPackets 或Winsock:TransmitFile,还需要将图像包装在适当的 HTTP 标头中
请注意,这些是特定于 MS 的扩展。
另见c++ - Bitmap transfer using winsock getdibits and setdibits
【讨论】: