2010-09-11 2 views
1

Может ли кто-нибудь указать мне, есть ли специальный способ отправки изображений (в частности .jpeg-файлов) через сокет tcp? До сих пор я разрабатываю веб-сервер, который, похоже, хорошо передает все текстовые данные. Когда дело доходит до jpeg-изображений, заголовки отправляются, однако консоль Cygwin просто зависает, когда дело доходит до отправки фактических данных.Отправка изображений через потоковый сокет

То, как я отправляю данные, заключается в том, что я сначала открываю файл, читаю данные в буфер и затем нажимаю на него. Какие-либо предложения?

while(!feof(sendFile)){ 

      bzero(send_buffer,sizeof(send_buffer)); 
      result = fread (send_buffer,1,sizeof(send_buffer),sendFile); 

      while(result>0){ 
       result = fread (send_buffer,1,sizeof(send_buffer),sendFile); 

       if(ferror(sendFile)){ 
        printf("Error reading file: %s\n",request_page); 
       } 
       if((test=send(new_fd,send_buffer,sizeof(send_buffer),0))<0){ 
        printf("Send returned %d\n",test); 
        printf("Sending %s Failed\n", request_page); 
        exit(1); 
       } 
       bzero(send_buffer,sizeof(send_buffer)); 
      } 
     } 
     fclose(sendFile); 
+0

что-то я узнал в передаче данных: Я буду обычно base64 кодирование перед отправкой и расшифровывает при получении, так что данные не будут потеряны при кодировании преобразования – mauris

+0

То верно, но я 'm записывает только код сервера. Я пытаюсь обслуживать запросы из существующего браузера, такого как Firefox. – BAkz

+0

Вам не нужно, чтобы base64 кодировал данные при использовании протокола HTTP. Он предназначен для обработки двоичных данных как есть. –

ответ

1

С этим кодом существует несколько неправильных или возможных ошибок.

result = fread (send_buffer,1,Fsize,sendFile); 

Эта строка читает Fsize байт из sendFile в send_buffer. Теперь я не вижу здесь, где вы получаете Fsize, но, учитывая его имя, я предполагаю, что это размер файла. Вы гарантировали, что send_buffer достаточно большой, чтобы держать Fsize байтов? Если нет, у вас есть потенциальный буфер, который переполняется здесь, что может привести к тому, что случайные данные будут записаны поверх вашего стека, что вызовет всевозможные проблемы. Вероятно, вы хотите читать в sizeof(send_buffer). У вас также, похоже, есть постоянная здесь, MAX_MSG. Это равно размеру буфера отправки? Если нет, эта строка также будет иметь проблемы. В общем, вы должны попытаться использовать один, последовательный метод обращения к размеру этого буфера, поэтому вы не путаете два разных значения и вызываете проблемы таким образом.

Далее, вы попробуете тестирование на ошибки чтения файла:

if(result != Fsize && (result!=0)) { 
printf("Reading error"); 
exit (1); 
} 

Теперь давайте посмотрим на то, что documentation для fread говорит:

Fread() и FWRITE () верните номер предметов, успешно прочитанных или написанных (т. е. не количество символов). Если произошла ошибка или достигнут конец файла , возвращаемое значение - короткий счетчик предметов (или ноль).

Fread() не делает различий между истекшим файла и ошибок, и вызывающие абоненты должны использовать feof (3) и FERROR (3), чтобы определить, какие произошло.

Здесь вы делаете ошибку, если не имеете точно Fsize или ноль. Теперь, согласно документам, у вас может быть либо короткий счет, либо нуль в случае ошибки или конца файла. Чтобы отличить, нужно ли вам сначала вырваться из цикла или умереть из-за ошибки, вам нужно будет позвонить feof и/или ferror.

Я бы предположил, что ваша ошибка заключается в переполнении буфера, упомянутом выше, но я бы рекомендовал исправить обе эти проблемы.

+0

Привет, Брайан, Большое спасибо за эти советы. Я исправил эти небольшие проблемы в своем коде, и это определило разницу - несколько страниц, которые я не мог открыть, прежде чем работать хорошо. Но у меня все еще есть проблемы с изображениями jpeg, хотя = s. – BAkz

+0

Я отредактировал мое сообщение с обновленным кодом. Оператор send() возвращает -1 и для жизни меня я не могу понять, почему ..: s – BAkz

+0

Ошибка, которую он дает: Соединение сбрасывается сверстником. Я предполагаю, что сокет как-то закрывается. Я включил параметр TCP_Keepalive, а также в setsockopt. Все еще никаких изменений .. – BAkz

1

Один из основных недостатков логики заключается в том, что вы вызываете fread() слишком много раз. Вы вызываете его один раз, а затем перед вызовом send() вы вызываете его снова , перезаписывая предыдущий буфер, который вам нужно отправить.

Вы также не проверяете, чтобы send() фактически отправлял полный буфер, прежде чем читать следующий.И вы полностью отправляете весь буфер, когда вы должны отправлять только количество байтов, которые fread() действительно читает.

Попробуйте вместо этого:

unsigned char send_buffer[...]; 
bool error = false; 

while (!feof(sendFile) && !error) 
{ 
    bzero(send_buffer, sizeof(send_buffer)); 

    result = fread(send_buffer, 1, sizeof(send_buffer), sendFile); 
    if (result < 1) 
    { 
     if (ferror(sendFile)) 
     { 
      printf("Error reading file: %s\n", request_page); 
      error = true; 
     } 
     break; 
    } 

    unsigned char *send_buffer_ptr = send_buffer; 
    do 
    { 
     test = send(new_fd, send_buffer_ptr, result, 0); 
     if (test <= 0) 
     { 
      printf("Send returned %d\n", test); 
      printf("Sending %s Failed\n", request_page); 
      error = true; 
      break; 
     } 

     send_buffer_ptr += test; 
     result -= test; 
    } 
    while (result > 0); 
} 

fclose(sendFile); 

if (error) 
    exit(1); 
Смежные вопросы