将图像写成C中的插座
我制作了可以将HTML提供给浏览器的服务器,但是由于某种原因,它不会发送图像。每当我在插座上发送图像时,浏览器都会收到一些图像,例如指定格式的标题,但图像的主体为/00/00/00/00仅为null字符。
这是代码:(我只是将响应标头从content-type:text/html更改为image/gif,所以忽略了变量的名称,我知道这是错误的。)
/*Refer to documentation for questions and functionality, as well as limitations*/
/*I have given each section of code an index in the form of a comment, which you can refer to in the documentation*/
#include <arpa/inet.h> /* htons() htonl() */
#include <unistd.h> /* read() write() */
#include <stdlib.h> /* exit() */
#include <string.h> /* strlen() strcat() */
#include <stdio.h> /* FILE scanf() printf() */
int main(void)
{
/*startof[a]*/
char filename[256];
FILE *file_pointer;
unsigned int file_size;
unsigned short int port_number;
struct sockaddr_in listening_socket_address;
int socket_address_size;
int listening_socketfd;
int new_socketfd;
struct sockaddr_in new_socket_address;
char HTTP_REQUEST[8192];
char file_buffer[2097152];
char HTTP_TEXT_RESPONSE_HEADER[] = "HTTP/1.0 200 OK\nContent-Type: image/*\n\n";
char HTTP_RESPONSE[2097152];
int response_size;
/*endof[a]*/
/*startof[b]*/
printf("Please enter the name of the file (text formats only) to be transmitted today, you can give a whole path, or just the name if it is in the same directory as this program :)\nFilename: ");
scanf("%255s", filename);
file_pointer = fopen(filename, "r");
fseek(file_pointer, 0L, SEEK_END);
file_size = ftell(file_pointer);
printf("File: %s is Size: %d Bytes\n", filename, file_size);
rewind(file_pointer);
printf("File: %s has been rewinded to position: 0\n\n", filename);
/*endof[b]*/
/*startof[c]*/
printf("Enter port number: ");
scanf("%hu", &port_number);
listening_socket_address.sin_family = AF_INET;
listening_socket_address.sin_port = htons(port_number);
listening_socket_address.sin_addr.s_addr = htonl(INADDR_ANY);
socket_address_size = sizeof(listening_socket_address);
/*endof[c]*/
/*startof[d]*/
listening_socketfd = socket(AF_INET, SOCK_STREAM, 0);
bind(listening_socketfd, (struct sockaddr *) &listening_socket_address, socket_address_size);
listen(listening_socketfd, 1);
new_socketfd = accept(listening_socketfd, (struct sockaddr *) &new_socket_address, &socket_address_size);
/*endof[d]*/
/*startof[e]*/
read(new_socketfd, HTTP_REQUEST, 8192);
printf("\nHere is the HTTP Request:\n\n%s", HTTP_REQUEST);
/*endof[e]*/
/*startof[f]*/
fread(file_buffer, 1, file_size, file_pointer);
strcat(HTTP_RESPONSE, HTTP_TEXT_RESPONSE_HEADER);
strncat(HTTP_RESPONSE, file_buffer, file_size);
response_size = sizeof(HTTP_TEXT_RESPONSE_HEADER) + file_size;
write(new_socketfd, (char*)HTTP_RESPONSE, response_size);
close(new_socketfd);
printf("Here is the HTTP response:\n\n%s", HTTP_RESPONSE);
/*endof[f]*/
return 0;
}
我正在使用的图像是GIF89A,并且浏览器能够说它是GIF89A,但是GIF内部的所有实际数据都是空字符。
我认为也许是因为图像是二进制的,因此它被浏览器(Firefox)使用的某些怪异格式/字节订单不事件砸碎,出于可移植性原因,我需要将其变成base64。
I made a server that can serve html to a browser, but for some reason it wont send images. Every time I send an image over the socket, the browser receives some of the image, like the headers specifying the format, but the body of the image is all /00/00/00 just null characters.
Here is the code: (I just changed the response header from content-type: text/html to image/gif, so ignore the name of the variable, I know it is wrong.)
/*Refer to documentation for questions and functionality, as well as limitations*/
/*I have given each section of code an index in the form of a comment, which you can refer to in the documentation*/
#include <arpa/inet.h> /* htons() htonl() */
#include <unistd.h> /* read() write() */
#include <stdlib.h> /* exit() */
#include <string.h> /* strlen() strcat() */
#include <stdio.h> /* FILE scanf() printf() */
int main(void)
{
/*startof[a]*/
char filename[256];
FILE *file_pointer;
unsigned int file_size;
unsigned short int port_number;
struct sockaddr_in listening_socket_address;
int socket_address_size;
int listening_socketfd;
int new_socketfd;
struct sockaddr_in new_socket_address;
char HTTP_REQUEST[8192];
char file_buffer[2097152];
char HTTP_TEXT_RESPONSE_HEADER[] = "HTTP/1.0 200 OK\nContent-Type: image/*\n\n";
char HTTP_RESPONSE[2097152];
int response_size;
/*endof[a]*/
/*startof[b]*/
printf("Please enter the name of the file (text formats only) to be transmitted today, you can give a whole path, or just the name if it is in the same directory as this program :)\nFilename: ");
scanf("%255s", filename);
file_pointer = fopen(filename, "r");
fseek(file_pointer, 0L, SEEK_END);
file_size = ftell(file_pointer);
printf("File: %s is Size: %d Bytes\n", filename, file_size);
rewind(file_pointer);
printf("File: %s has been rewinded to position: 0\n\n", filename);
/*endof[b]*/
/*startof[c]*/
printf("Enter port number: ");
scanf("%hu", &port_number);
listening_socket_address.sin_family = AF_INET;
listening_socket_address.sin_port = htons(port_number);
listening_socket_address.sin_addr.s_addr = htonl(INADDR_ANY);
socket_address_size = sizeof(listening_socket_address);
/*endof[c]*/
/*startof[d]*/
listening_socketfd = socket(AF_INET, SOCK_STREAM, 0);
bind(listening_socketfd, (struct sockaddr *) &listening_socket_address, socket_address_size);
listen(listening_socketfd, 1);
new_socketfd = accept(listening_socketfd, (struct sockaddr *) &new_socket_address, &socket_address_size);
/*endof[d]*/
/*startof[e]*/
read(new_socketfd, HTTP_REQUEST, 8192);
printf("\nHere is the HTTP Request:\n\n%s", HTTP_REQUEST);
/*endof[e]*/
/*startof[f]*/
fread(file_buffer, 1, file_size, file_pointer);
strcat(HTTP_RESPONSE, HTTP_TEXT_RESPONSE_HEADER);
strncat(HTTP_RESPONSE, file_buffer, file_size);
response_size = sizeof(HTTP_TEXT_RESPONSE_HEADER) + file_size;
write(new_socketfd, (char*)HTTP_RESPONSE, response_size);
close(new_socketfd);
printf("Here is the HTTP response:\n\n%s", HTTP_RESPONSE);
/*endof[f]*/
return 0;
}
The image I am using is a gif89a, and the browser is able to tell it is a gif89a, but all the actual data inside the gif is just null characters.
I am thinking that perhaps because the image is in binary, it is being smashed by some weird formatting/ byte order mishap that the browser(firefox) is using, an I need to turn it into base64 for portability reasons.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
此代码有很多错误,但最重要的是,您根本没有发送有效的HTTP响应:
您必须使用
\ r \ n
进行换行。图像/*
不是单个文件的有效媒体类型,使用更合适的媒体类型,例如image/gif
等。。
您缺少<
代码> content-Length 标题指定图像的大小,因为您没有使用HTTP的
块
传输编码。请勿使用
sizef(http_text_response_header)
,其中包括null-terminator。使用strlen()
而不是。不要使用
strncat()
将 binary 数据附加到char []
array。这将破坏第一个0x00
遇到的字节。以 binary 模式打开图像文件。
不要尝试
write()
单个发送中的全部 http响应。那根本不起作用。内核缓冲区可能不够大,无法将其全部发送。接收器的内核缓冲区可能不够大,无法接收全部。您需要注意write()
的返回值,这将告诉您内核实际接受了多少个字节以发送。调用write()
在循环中,直到所有字节都被接受为止。话虽如此,请尝试更多类似的东西:
There are a lot of things wrong with this code, but most importantly, you are simply not sending a valid HTTP response:
You must use
\r\n
for line breaks.image/*
is not a valid media type for a single file, use a more appropriate media type, likeimage/gif
, etc.You are missing a
Content-Length
header to specify the image's size, since you are not using HTTP'schunked
transfer encoding.Do not use
sizeof(HTTP_TEXT_RESPONSE_HEADER)
, which includes the null-terminator. Usestrlen()
instead.Don't use
strncat()
to append binary data to achar[]
array. That will break on the first0x00
byte encountered.Open image files in binary mode.
Don't try to
write()
the entire HTTP response in a single send. That simply will not work. The kernel buffer may not be large enough to send it all. The receiver's kernel buffer may not be large enough to receive it all. You need to pay attention to the return value ofwrite()
, which will tell you how many bytes were actually accepted by the kernel for sending. Callwrite()
in a loop until all of the bytes have been accepted.With that said, try something more like this: