[英]C sockets, jpeg image not displaying properly
I'm learning about sockets and Im in the process of creating a socket server which can serve html files, as well as images in the jpeg
format.我正在学习 sockets 和 Im 在创建可以提供 html 文件以及
jpeg
格式的图像的套接字服务器的过程中。 Based on other similar posts I've found, I can't deduce what I'm doing wrong.根据我发现的其他类似帖子,我无法推断出我做错了什么。 I use
fseek
and ftell
to get the size of the image, and then I use fread
to read those bytes into a malloc
'ed character array, which I then send back.我使用
fseek
和ftell
来获取图像的大小,然后使用fread
将这些字节读入malloc
的字符数组,然后将其发回。 What am I doing wrong?我究竟做错了什么?
code for dealing with jpeg
files:处理
jpeg
文件的代码:
else if (!strcmp(getFileExtension(fname), "jpg") || !strcmp(getFileExtension(fname), "jpeg"))
{
printf("got a jpeg request\n");
FILE *fp = fopen(fname, "rb");
if (fp == NULL)
{
perror("Error opening .jpg/.jpeg file");
status = 500;
ret = toStr(status);
statusMessage = " Internal Server Error\n";
body = "<h1>Server encountered error trying to open jpeg file</h1>";
mode = html;
goto shutdown;
}
// seek to end of file and get
// length of the file to read
fseek(fp, 0, SEEK_END);
bodySize = ftell(fp);
printf("file is %d bytes\n", bodySize);
// seek back to beginning of file
fseek(fp, 0, SEEK_SET);
// allocate and read len amt of bytes
char *data = malloc(bodySize);
fread(data, sizeof(char), bodySize, fp);
fclose(fp);
status = 200;
ret = toStr(status);
statusMessage = " OK\n";
body = data;
mode = jpeg;
goto shutdown;
}
my shutdown
code, which simply sets the headers, status codes, etc. The jpeg file data should be within the body
variable我的
shutdown
代码,它只是设置标题、状态代码等。jpeg 文件数据应该在body
变量中
// cleanup and closing
shutdown:
// send just the headers first
size = strlen(header) + strlen(ret) + strlen(statusMessage) + strlen(mode) + 1;
reply = (char *)malloc(size);
reply[size - 1] = '\0';
snprintf(reply, size, "%s%s%s%s", header, ret, statusMessage, mode);
printf("\n%s\n\n", reply);
send(new_sd, reply, size, 0);
// send just body
if (!strcmp(mode, jpeg)) // jpeg uses bodySize
{
printf("body size (%d):\n%s\n", bodySize, body);
send(new_sd, body, bodySize, 0);
}
else // non jpeg uses strlen
{
printf("body size (%d):\n%s\n", (int)strlen(body), body);
send(new_sd, body, strlen(body), 0);
}
shutdown(new_sd, SHUT_RDWR);
close(new_sd);
exit(0);
Here is my server response to the browser(client):这是我的服务器对浏览器(客户端)的响应:
Nothing stands out to me in terms of the socket code.就套接字代码而言,我没有什么特别突出的。 Instead of this being a socket (only) issue, maybe it is (also) a protocol issue?
这不是一个(唯一的)套接字问题,也许它(也是)一个协议问题? Possibly a non-compliance issue with the HTTP/1.1 ( RFC 7230 +)?
可能是 HTTP/1.1( RFC 7230 +)的不合规问题? neither Content-Length nor Transfer-Encoding specified?
既没有指定 Content-Length 也没有指定 Transfer-Encoding? bad line endings?
行尾不好? (status line would normally end with OK\r\n not OK\n\n)
(状态行通常以 OK\r\n not OK\n\n 结尾)
shouldn't use snprintf
with %s
for binary data like jpeg bytes, I believe %s
terminates at null byte (0x00) which makes the binary file corrupt.不应将
snprintf
与%s
一起用于 jpeg 字节等二进制数据,我相信%s
在 null 字节 (0x00) 处终止,这会使二进制文件损坏。
Also strlen(body)
won't work either as strlen will also terminate at null byte (0x00) giving bad length for the jpeg data.同样
strlen(body)
也不起作用,因为 strlen 也将在 null 字节 (0x00) 终止,从而为 jpeg 数据提供错误的长度。
Try memcpy
instead.改用
memcpy
。
Open the file with this mode "rb+"
使用此模式
"rb+"
打开文件
Simple pseudo-code (might not compile)简单的伪代码(可能无法编译)
int jpegDataSize = len;
char* jpegdata = data;
reply_size = strlen(HEADER) + strlen(ret) + strlen(statusMessage) + strlen(mode) + jpegDataSize + 1; //can't use strlen for jpeg because it's binary
reply = (char *)malloc(reply_size);
memcpy(&reply[0], HEADER, strlen(HEADER));
memcpy(&reply[strlen(HEADER)], ret, strlen(ret));
memcpy(&reply[strlen(ret)], statusMessage, strlen(statusMessage));
memcpy(&reply[strlen(statusMessage)], mode, strlen(mode));
memcpy(&reply[strlen(mode)], jpegdata, jpegDataSize); //avoid strlen(jpegdata)
reply[reply_size - 1] = '\0';
printf("\n-------------------------------------\nresponse is (%d): \n%s\n\n", reply_size, reply); //can't use strlen (because jpegdata is binary)
send(new_sd, reply, reply_size, 0); //can't use strlen because jpegdata is binary.
shutdown(new_sd, SHUT_RDWR);
close(new_sd);
exit(0);
Turns out there is no logistical issue to my edited post's code.事实证明,我编辑的帖子代码没有后勤问题。 The problem was that in the shutdown code, when I send the HTTP header reply, I used size as the length for the reply, when I should have used
strlen(reply)
or size - 1
for send(new_sd, reply, size, 0)
.问题是在关机代码中,当我发送 HTTP header 回复时,我使用 size 作为回复的长度,而我应该使用
strlen(reply)
或size - 1
send(new_sd, reply, size, 0)
.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.