Передача аудио файла с использованием сокетов c - PullRequest
1 голос
/ 07 февраля 2012

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

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

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

1 Ответ

4 голосов
/ 07 февраля 2012

Вы, кажется, читаете из двоичного файла данных, но внутри вашей функции 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 и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...