使用C套接字在HTTP响应中发送二进制文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用C套接字在HTTP响应中发送二进制文件相关的知识,希望对你有一定的参考价值。

我试图在http响应中发送二进制文件(png图像)。

FILE *file;
char *buffer;
int fileLen;

//Open file
file = fopen("1.png", "rb");
if (!file)
{
    return;
}

//Get file length
fseek(file, 0, SEEK_END);
fileLen=ftell(file);
fseek(file, 0, SEEK_SET);

//Allocate memory
buffer=(char *)malloc(fileLen+1);
if (!buffer)
{
    fprintf(stderr, "Memory error!");
    fclose(file);
    return;
}

//Read file contents into buffer
fread(buffer, fileLen, 1, file);
fclose(file);
//free(buffer);




char header[102400];

sprintf(header, 
"HTTP/1.1 200 OK
"
"Date: Thu, 19 Feb 2009 12:27:04 GMT
"
"Server: Apache/2.2.3
"
"Last-Modified: Wed, 18 Jun 2003 16:05:58 GMT
"
"ETag: "56d-9989200-1132c580"
"
"Content-Type: image/png
"
"Content-Length: %i
"
"Accept-Ranges: bytes
"
"Connection: close
"
        "
", fileLen);

char *reply = (char*)malloc(strlen(header)+fileLen);
strcpy(reply, header);
strcat(reply, buffer);

printf("msg %s
", reply);


//return 0;
int sd = socket(PF_INET, SOCK_STREAM, 0);

struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(8081);
addr.sin_addr.s_addr = INADDR_ANY;

if(bind(sd,&addr,sizeof(addr))!=0)
{
    printf("bind error
");
}

if (listen(sd, 16)!=0)
{
    printf("listen error
");
}

for(;;)
{
    int size = sizeof(addr);
    int client = accept(sd, &addr, &size);

    if (client > 0)
    {
        printf("client connected
");
        send(client, reply, strlen(reply), 0);
    }
}

但是我的浏览器不理解这个=(我到底做错了什么?

UPD:我试图发送文本数据 - 没关系。但二进制数据失败了

答案

问题是你的邮件正文被视为一个以空字符结尾的文本字符串(你在它上面使用strcatstrlen),当它不是一个时:它是二进制数据(PNG文件)。因此,strcatstrlen都停在图像的前0个字节上(通常很早)。

你的程序甚至打印出响应体:注意它给出了正确的头,但是一旦PNG头(二进制数据)启动,只有几个字节。

  1. strcat(reply, buffer),其中buffer可能包含0个字节。将其更改为memcpy(reply+strlen(header), buffer, fileLen)
  2. send(client, reply, strlen(reply), 0),其中reply可能包含0个字节。预先计算回复的长度,或用strlen(header)+fileLen替换strlen。

另一个错误是,当你完成后你没有关闭连接,所以浏览器将永远等待。你需要这个,在send之后:

close(client);
另一答案

HTTP协议指定它期望“ r n”而不是“ n”。试试吧。 :)

另一答案
strcat(reply, buffer); // this is incorrect, because png(buffer) may contain zero byte
send(client, reply, strlen(reply), 0);
strlen(reply) // this is incorrect, because png may contain zero byte
另一答案

我试图按照你所做的但无法让它发挥作用。相反,我发现分开发送标题和文件更容易。

EG

send(client, header, strlen(header), 0);
send(client, buffer, fileLen + 1, 0);

以上是关于使用C套接字在HTTP响应中发送二进制文件的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 C 中的 HTTP POST 请求发送图像或二进制数据

如何仅使用套接字库通过 Python 正确发送 HTTP 响应?

如何使用C / C ++套接字从HTTP读取二进制文件

使用套接字发送文件

C:发送文件到套接字

C++ 如何使用 Socket 类向 HTTP 服务器发送数据和接收响应