2015-06-01 104 views
0

我現在面臨一個問題,試圖通過套接字發送MP3文件在插座用C

這送的MP3文件的代碼,我用它來讀取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); 
} 

如果我緩衝器(音頻從第一段代碼 VAR)保存到一個文件之前發送,它的偉大工程,但是當我嘗試將它保存在服務器端,它會被損壞。另外,緩衝區的內容是這個?? $?

我不知道爲什麼,我認爲這是因爲是一個二進制文件。

有什麼想法?也許我以錯誤的方式發送數據?

在此先感謝

+0

好吧,它已經strlen的()中,因此它不能很好。所有使用strlen()調用的網絡/套接字代碼中有99%是borken。 –

+0

@MartinJames假設二進制流爲100%。 –

+0

我試過用sizeof(message)但是是一樣的東西... – 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()'使用一行代碼發送數據,並直接執行,而不必在讀取數據時將數據複製到用戶空間,然後在寫入套接字時返回數據。 –