2015-06-01 3 views
0

Я столкнулся с проблемой, пытаясь отправить файл mp3 через сокетОтправить mp3 файл через сокет в C

Это код я использую, чтобы прочитать файл mp3

FILE *file; 
char *audio; 
unsigned long fileLen; 

file = fopen("AAAA.mp3", "rb"); 
if (!file) 
{ 
    fprintf(stderr, "Unable to open file"); 
    return; 
} 

fseek(file, 0, SEEK_END); 
fileLen = ftell(file); 
fseek(file, 0, SEEK_SET); 

audio = (char *)malloc(fileLen+1); 
if (!audio) 
{ 
    fprintf(stderr, "Memory error!"); 
    fclose(file); 
    return; 
} 

fread(audio, fileLen, 1, file); 
fclose(file); 

И тогда я имеет эту функцию, чтобы отправить Контент

int send_message(int sockfd, uint16_t code, char *message) 
{ 
    int bytes_sent; 
    uint16_t l_msg; 
    uint16_t l_msg_net; 
    char buffer[BUFFER_SIZE+CODE_LEN+MSG_LEN]; 

    l_msg = strlen(message) + 1; 
    l_msg_net = htons(l_msg); 

    code = htons(code); 

    // Save message code 
    memcpy(buffer, &code, CODE_LEN); 
    // Save message length 
    memcpy(buffer + CODE_LEN, &l_msg_net, MSG_LEN); 
    // Save message 
    memcpy(buffer + CODE_LEN + MSG_LEN, message, l_msg); 

    bytes_sent = send(sockfd, buffer, (l_msg + CODE_LEN + MSG_LEN), 0); 

    return(bytes_sent); 
} 

Если я сохранить буфер (аудио вара из первой части коды) в файл, прежде чем отправить его, он прекрасно работает, но когда я попробуйте сохранить его на стороне сервера, он будет поврежден. Кроме того, содержимое буфера это? $?

Я не знаю, почему, я думаю, это потому, что это двоичный файл.

Любые мысли? Может быть, я отправляю данные неправильно?

Заранее спасибо

+0

Ну, это STRLEN() в нем, так что это не может быть хорошим. 99% всего кода сети/сокета с вызовами strlen() - borken. –

+0

@MartinJames Это 100%, предполагающий двоичные потоки. –

+0

Я пробовал с sizeof (сообщение), но это то же самое ... – Ernes

ответ

0

Это двоичный файл, то есть байты, содержащие '\0' законные данные.

Эта линия:

fileLen = ftell(file); 

говорит вам, сколько байт для отправки.

Также send() возвращает ssize_t, а не int. Согласно man page:

ssize_t send(int sockfd, const void *buf, size_t len, int flags); 

еще лучше, отправить файл непосредственно с помощью sendfile():

struct stat sb; 
int fd = open("AAAA.mp3", O_RDONLY); 
fstat(fd, &sb); 
// first send the file size - NB this is not correct as it 
// assumes sizeof(sb.st_size) is the same on the other 
// end *and* has the same endianness 
write(sockfd, &sb.st_size, sizeof(sb.st_size)); 
ssize_t bytesSent = sendfile(sockfd, fd, NULL, sb.st_size); 
+0

Итак, нет другого способа отправить файл, а не использовать sendfile? Дело в том, что я не понимаю, почему данные повреждены с другой стороны. Кажется, я не могу отправить буфер как «строку» – Ernes

+0

@Ernes - вы не можете отправить его как строку, потому что это ** не ** строка. И есть много способов отправить файл из сокета, если вы хотите написать код. Все они в значительной степени включают в себя запись нескольких строк кода для копирования данных в пространство пользователя, а затем запись их в сокет. 'sendfile()' отправляет данные с использованием одной строки кода и делает это напрямую, не копируя данные в пространство пользователя, когда он читается, а затем возвращается, когда он записывается в сокет. –

Смежные вопросы