Отправка изображений через потоковый сокет - PullRequest
1 голос
/ 11 сентября 2010

Может кто-нибудь подсказать мне, существует ли особый способ отправки изображений (в частности, файлов .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);

Ответы [ 2 ]

1 голос
/ 12 сентября 2010

У вас есть один главный логический недостаток: вы слишком часто вызываете функцию 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);
1 голос
/ 11 сентября 2010

В этом коде есть несколько вещей неправильных или потенциально неправильных.

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);
}

Теперь давайте посмотрим, что в документации для fread сказано:

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

fread () не различает конец файла и ошибка, и вызывающие необходимо использовать feof (3) и ferror (3) для определить, что произошло.

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

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

...