2011-03-31 17 views
6

का उपयोग कर HTTP प्रतिक्रिया में बाइनरी फ़ाइल भेजें मैं 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); 
    } 
} 

लेकिन अपने ब्राउज़र को नहीं समझता यह = (क्या मैं गलत कर रहा हूँ वास्तव में

युपीडी: मैं पाठ डेटा भेजने की कोशिश की - इसके ठीक लेकिन बाइनरी डेटा विफल रहता है

उत्तर

7

समस्या यह है कि आपके संदेश के मुख्य भाग एक अशक्त-समाप्त पाठ स्ट्रिंग के रूप में इलाज किया जा रहा है (आपका उपयोग 210 और strlen उस पर), जब यह एक नहीं है: यह बाइनरी डेटा (एक पीएनजी फ़ाइल) है। इसलिए, strcat और strlen दोनों छवि में पहले 0 बाइट (आमतौर पर काफी जल्दी) पर रुकते हैं।

आपका प्रोग्राम प्रतिक्रिया शरीर को भी प्रिंट कर रहा है: ध्यान दें कि यह सही शीर्षलेख देता है, लेकिन एक बार पीएनजी हेडर (बाइनरी डेटा) शुरू होता है, तो केवल कुछ बाइट्स होते हैं।

  1. लाइन strcat(reply, buffer), जहां buffer संभावित रूप से 0 बाइट्स शामिल हैं। इसे memcpy(reply+strlen(header), buffer, fileLen) पर बदलें।
  2. लाइन send(client, reply, strlen(reply), 0), जहां reply संभावित रूप से 0 बाइट्स शामिल हैं। उत्तर की लंबाई की पूर्व-गणना करें, या strlen(header)+fileLen के साथ स्ट्रेल को प्रतिस्थापित करें।

एक और बग यह है कि जब आप पूरा कर लेंगे तो आप कनेक्शन बंद नहीं कर रहे हैं, इसलिए ब्राउज़र हमेशा के लिए इंतजार करेगा। आप इस की जरूरत है, send के बाद:

close(client); 
+0

ध्यान दें कि यह वास्तव में आपके द्वारा डाले गए डिबगिंग प्रिंट को ठीक नहीं करेगा, क्योंकि यह printf का उपयोग करता है और जब यह शून्य बाइट हिट करता है तो रुक जाएगा। लेकिन सॉकेट व्यवहार सही होगा; मैंने इसे एक वेब ब्राउज़र में परीक्षण किया और यह काम किया। – mgiuca

1

HTTP प्रोटोकॉल?। यह बताता है कि यह उम्मीद "\ r \ n" के बदले "\ n"। कि कोशिश करो। :)

+0

नहीं, इससे मदद नहीं मिली। मैंने टेक्स्ट डेटा भेजने की कोशिश की - यह ठीक है "\ n"। लेकिन बाइनरी डेटा – spe

+0

विफल रहता है विंडोज स्वचालित रूप से \ n \ r \ n आउटपुट – dns

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

0

मैं तुम्हें क्या किया पालन करने के लिए कोशिश की, लेकिन यह काम करने के लिए नहीं मिल सका। इसके बजाए, मुझे केवल हेडर भेजने और फ़ाइल को अलग करना आसान लगता है।

उदा।

send(client, header, strlen(header), 0); 
send(client, buffer, fileLen + 1, 0); 
संबंधित मुद्दे