(C ++) Отправка файлов JPG через сокеты - PullRequest
0 голосов
/ 04 ноября 2010

Я изучаю программирование на C / C ++ с помощью сокетов и пытаюсь переместить двоичный файл с сервера на клиент. Вот что у меня на стороне сервера.

ifstream file(argv[1],ios::binary|ios::ate)
size = new char[file.tellg()]
memblock = new char[size]
file.seekg(0,ios::beg);
file.read(memblock,size);

После прочтения содержимого бинарного файла в мембрану я передаю его через функцию сокета read.

listen(sockd, 5);
newsock=accept(sockfd, NULL, NULL);
write(newsock, memblock, strlen(memblock));
delete[] memblock; 

Между тем, на стороне клиента

connect(sockfd, &servaddr, sizeof(servaddr));
read(sockfd, buffer, size);
ofstream output(argv[1], ios::binary);
output.write(buffer, strlen(buffer));
output.close(); 
delete[] buffer 

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

Теперь сам исходный код составляет 1 КБ (если быть точным, 714 байт). Когда я загружаю его в серверную программу, он правильно сообщает, что strlen (buffer) равен 715. И при запуске клиента он также правильно сообщает о чтении 715 байтов, и я получаю хороший выходной файл, идентичный original_source_code.cpp * 1012. *

Однако у меня есть 512-байтовый файл jpg. Программа сервера сообщает, что strlen (буфер) правильно равен 512, однако клиент считывает только 4 байта и останавливается. Количество прочитанных байтов варьируется в зависимости от формата файла, но он никогда не читает весь буфер. Однако текстовые файлы передаются через сокеты без каких-либо проблем.

Какие-либо причины, почему это происходит? Я даже не могу сделать это на той же машине, что и при запуске экземпляра сервера и попросить экземпляр клиента подключиться к 127.0.0.1.

Любые предложения будут оценены!

Ответы [ 2 ]

2 голосов
/ 04 ноября 2010

strlen(buffer) считает длину строки.Строка завершается 0, ваш двоичный файл может содержать нули до конца файла.

Так что strlen вернет меньше размера файла.

Используйте sizeвместо переменной.

1 голос
/ 04 ноября 2010

У вас есть две проблемы здесь:

  1. strlen() оканчивается на \0 (см. Ответ @taspeotis)
  2. Вы должны зациклить read(); вручную:
int total_read = 0;
int r = 0;
while ( ( r = read(sockfd, buffer + total_read , size) ) > 0 )
        total_read += r;

или даже лучше:

connect(sockfd, &servaddr, sizeof(servaddr));
ofstream output(argv[1], ios::binary);

int byteread;
while ((byteread = read(sockfd, buffer, buffersize)) > 0 )
    output.write(buffer, byteread);
output.close(); 
delete[] buffer 
...