2011-03-31 57 views
6

我試圖在http響應中發送二進制文件(png圖像)。使用C套接字在HTTP響應中發送二進制文件

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\n" 
"Date: Thu, 19 Feb 2009 12:27:04 GMT\n" 
"Server: Apache/2.2.3\n" 
"Last-Modified: Wed, 18 Jun 2003 16:05:58 GMT\n" 
"ETag: \"56d-9989200-1132c580\"\n" 
"Content-Type: image/png\n" 
"Content-Length: %i\n" 
"Accept-Ranges: bytes\n" 
"Connection: close\n" 
     "\n", fileLen); 

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

printf("msg %s\n", 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\n"); 
} 

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

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

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

,但我的瀏覽器不明白這一點=(我在做什麼錯究竟

UPD:我試圖發送文本數據 - 它的好,但二進制數據失敗

回答

7

的問題是,你的郵件正文被視爲空值終止字符串(您使用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); 
+0

請注意,這實際上並不會修復您放入的調試打印,因爲它使用printf,並在它遇到空字節時停止。但套接字行爲將是正確的;我在網絡瀏覽器中測試了它,它工作。 – mgiuca 2011-03-31 07:41:52

1

HTTP協議?規定稱,預計爲「\ r \ n」,而不是「\ n」試試。:)

+0

不,這沒有幫助。我試圖發送文本數據 - 它確定與「\ n」。但二進制數據失敗 – spe 2011-03-31 07:12:14

+0

Windows自動將\ n轉換爲\ r \ n輸出 – dns 2013-05-13 14:51:21

0
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 
+0

不僅如此,請注意,緩衝區中的'strcat'在響應空字節時也會失敗 - 請參閱我的答案。 – mgiuca 2011-03-31 07:40:57

0

我想跟着你做了什麼,但不能讓它開始工作。相反,我發現分開發送頭文件和文件更容易。

例如

send(client, header, strlen(header), 0); 
send(client, buffer, fileLen + 1, 0); 
相關問題