2012-02-06 2 views
1

Я пытаюсь отправить аудиофайл с одного компьютера на другой с помощью программирования сокетов в c. Когда я отправляю простую строку без какой-либо информации кадрирования, такой как заголовок или порт, она отправляется отлично. Но когда я пытаюсь отправить ту же информацию с некоторой информацией заголовка, как размер socket_data или packet_no. он не отправляется должным образом. Даже вывод терминала SAME на обеих машинах, но создаваемый файл полностью отличается и не воспроизводится. Я использовал концепцию сериализации для отправки пакета. У меня есть коды. Пожалуйста, прокомментируйте, что происходит не так.Передача аудиофайла с использованием c сокетов

Server.c

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <fcntl.h> 

void set_socket(struct sockaddr_in *socket, int type, int host_short, int addr_type) 
{ 
    socket -> sin_family = type; 
    socket -> sin_port = htons(host_short); 
    socket -> sin_addr.s_addr = htonl(addr_type); 
} 

void serialize(char *buffer, int count, char *data) 
{ 
    int i=0, j=0; 
    char temp1[20]; 

    sprintf(temp1, "%d", count); 
    while(temp1[i] != '\0') 
    { 
     buffer[j++] = temp1[i++]; 
    } 
    buffer[j++]=' '; 

    for(i=0; data[i] != '\0'; i++) 
    { 
     buffer[j++] = data[i]; 
    } 
    buffer[j] = '\0'; 
    printf("BUFFER =%ld\n", sizeof(buffer)); 
} 

int main() 
{ 
    int sid = 0, bid = 0, fp; 
    char *send_data = (char *)malloc(1024*sizeof(char)); 
    char temp[1024]; 
    char *receive_data = (char *)malloc(1024*sizeof(char)); 
    int fd, count, cnt=0; 
    struct sockaddr_in server_socket, client_socket; 
    int size = sizeof(client_socket); 

    if((sid = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 
    { 
     printf("Connection error..\n"); 
     exit(1); 
    } 

    set_socket(&server_socket, AF_INET, 6000, INADDR_ANY); 

    if((bid = bind(sid, (struct sockaddr *)&server_socket, sizeof(struct sockaddr))) == -1) 
    { 
     printf("Binding error..\n"); 
     exit(1); 
    } 

    printf("I am waiting for client..\n"); 

    recvfrom(sid, receive_data, 1024, 0,(struct sockaddr *)&client_socket, &size); 
    printf("received data is : %s\n", receive_data); 
    fd = open(receive_data, O_RDONLY); 
    printf("size = %ld\n", sizeof(send_data)); 

    while((count=read(fd, temp, 500)) != 0) 
    { 
     printf("I am inside the loop : %d\n", cnt++); 
     serialize(send_data, count, temp); 
     printf("Serialized : %s\n", send_data); 
     sendto(sid, send_data, 1024, 0, (struct sockaddr *)&client_socket, size); 
    } 
    printf("I am outside the loop : %d\n", count); 
    strcpy(temp, "ENDOFFILE"); 
    serialize(send_data, sizeof(temp), temp); 
    sendto(sid, send_data, 1024, 0, (struct sockaddr *)&client_socket, size); 

    fcloseall(); 
    close(sid); 
    close(fd); 
    return 0; 
} 

Client.c

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <fcntl.h> 

void set_socket(struct sockaddr_in *socket, int type, int host_short) 
{ 
    socket -> sin_family = type; 
    socket -> sin_port = htons(host_short); 
} 

void deserialize(char *buffer, int *size, char *data) 
{ 
    int i=0, j=0; 
    char temp1[20]; 

    while(buffer[i] != ' ') 
    { 
     temp1[j++] = buffer[i++]; 
    } 
    temp1[j] = '\0'; 
    printf("\nINT : %s\n", temp1); 
    *size = atoi(temp1); 

    i++; 
    j=0; 

    while(buffer[i] != '\0') 
    { 
     data[j++] = buffer[i++]; 
    } 
    data[j++] = '\0'; 
} 

int main() 
{ 
    int sid = 0, bid = 0, con = 0; 
    char *send_data = (char *)malloc(1024*sizeof(char)); 
    char *receive_data = (char *)malloc(1024*sizeof(char)); 
    char *temp = (char *)malloc(1024*sizeof(char)); 
    struct hostent *host; 
    struct sockaddr_in server_socket; 
    int size = sizeof(server_socket); 

    if((sid = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 
    { 
     printf("Connection error at client side..\n"); 
     exit(1); 
    } 

    set_socket(&server_socket, AF_INET, 6000); 

    if (inet_aton("127.0.0.1", &server_socket.sin_addr)==0) 
    { 
     fprintf(stderr, "inet_aton() failed\n"); 
     exit(1); 
    } 

    printf("Enter the name of the file you want to see : "); 
    scanf("%s", send_data); 
    int fd = open("sanket.mp3", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IXUSR); 
    sendto(sid, send_data, 1024, 0, (struct sockaddr *)&server_socket, size); 
    printf("================= Contents of the File =====================\n"); 
    while(1) 
    { 
     int size; 
     recvfrom(sid, temp, 1024, 0, (struct sockaddr *)&server_socket, &size); 
     printf("Deserialize it : %s\n",temp); 
     deserialize(temp, &size, receive_data); 
     if(!strcmp(receive_data, "ENDOFFILE")) 
     { 
      printf("============================================================\n"); 
      break; 
     } 
     else 
      write(fd, receive_data, size); 
    } 
    fcloseall(); 
    close(sid); 

    return 0; 
} 

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

+0

Может иметь какое-то отношение к контенту. Есть ли вероятность, что ваша кодировка может отличаться и между машинами? –

+0

Похоже, вы отправляете файлы через UDP вместо TCP. Это намеренно? – grieve

+0

Если вы решили использовать TCP вместо UDP, этот ответ из другого сообщения может помочь вам: http://stackoverflow.com/a/666788/34329 – grieve

ответ

4

Вы, кажется, читаете из двоичного файла данных, но внутри вашей функции serialize вы обрабатываете данные как-бы если они были строковыми данными с нулевым завершением. Так, например, этот цикл внутри serialize:

for(i=0; data[i] != '\0'; i++) 
{ 
    buffer[j++] = data[i]; 
} 

прекращается на первом нулевом значении он сталкивается. Если это истинные двоичные данные из вашего аудиофайла, то я уверен, что вы получите 0 значения, которые являются фактическими аудиоданными, а не указывают конец буфера. Вместо завершения значения NULL вы должны оканчивать размер буфера, который вы передаете, на serialize, который был прочитан в вашем вызове read в цикле while. Таким образом, вы можете быть уверены, что получаете все данные, которые были прочитаны из вашего вызова read, упакованного в ваш буфер отправки.

Во-вторых, печать sizeof(buffer), когда buffer является указателем, будет печатать только размер указателя, а не размер фактического буфера, на который указывает указатель. Опять же, вам придется явно передать это значение вашей функции serialize.

В-третьих, вы завершаете буфер нулевым значением ... опять же, это не будет хорошей идеей, основанной на первом вопросе о том, что это необработанные двоичные данные, а не строки с нулевым завершением. Вы должны либо придумать строку какого-либо типа, чтобы указать конец передачи в буфере, который будет набором значений, которые невозможно было бы быть частью данных, либо вы должны явно прочитать количество байтов, которые являются в «счете», который вы встроили в пакетные данные.

И, наконец, вы не сериализуете свои данные ... концепция сериализации обычно означает передачу данных независящим от платформы способом. Вы просто собираете прочитанные байты и отправляете их по сети, предполагая, что принимающая сторона имеет одинаковую идентификатор и т. Д. Достаточно простой подход к сериализации мог бы сделать что-то вроде создания строк ASCII из всех значений данных, а нижняя сторона что это создаст довольно много раздувания данных. Существуют и другие межплатформенные стандарты для сериализованных данных, таких как JSON, SOAP и т. Д.

+0

Большое спасибо .. Он работал как шарм. – curiousMind

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