1

I am trying to send audio file from one computer to other using socket programming in c. When I send simple string without any framing information such as header or tailer it gets sent perfectly. But when I try to send the same information with some header information like size of the socket_data or packet_no. it doesn't get sent properly. Even the terminal output is SAME on both the machines but the file which gets created is totally different and unplayable. I have used serializing concept to send packet. Am attaching codes. Please comment whats going wrong.

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

When I checked the size of the sent and received file, sizes are same but the contents are different, thus I am unable to play received audio file.

curiousMind
  • 155
  • 3
  • 10
  • Could have something to do with endianness. Is there any chance that your encoding could be different between the machines as well? – Richard J. Ross III Feb 06 '12 at 20:50
  • It looks like you are sending the files over UDP instead of TCP. Is that intentional? – grieve Feb 06 '12 at 21:06
  • If you choose to use TCP instead of UDP, this answer from another post may help you: http://stackoverflow.com/a/666788/34329 – grieve Feb 06 '12 at 21:46
  • RichardJ.RossIII : The program is not even working on single machine. grieve : Yes, am sending packets through UDP intentionally. – curiousMind Feb 07 '12 at 09:18

1 Answers1

4

You seem to be reading from a binary data-file, yet inside your serialize function you are treating the data as-if it were null-terminated string data. For instance, this loop inside serialize:

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

will terminate on the first zero-value it encounters. If this is true binary data from your audio file though, then I'm sure you'll get 0 values that are actual audio data rather than indicating the end of the buffer. Instead of terminating on a NULL-value, you should be terminating on the size of the buffer that you're passing to serialize that was read in your call to read in the while-loop. That way you can be sure you are getting all the data that was read from your read call packed into your send-buffer.

Secondly, printing sizeof(buffer), when buffer is a pointer, will only print the size of a pointer-type, not the size of the actual buffer the pointer is pointing to. Again, you're going to have to explicitly pass that value to your serialize function.

Third, you're terminating the buffer with a null-value ... again, that's not going to be a good idea based on the first point about this being raw binary data and not null-terminated strings. You should either come up with some type of string to indicate the end-of-transmission in the buffer that would be a set of values that would be impossible to be part of the data, or you should explicitly read the number of bytes that are in the "count" that you've embedded in the packet data.

Finally, you're not really serializing your data ... the concept of serializing typically means to transfer the data in a platform-independent way. You're simply packing up the bytes read and sending them across the network, assuming that the receiving side has the same endianness, etc. A fairly simple serialization approach would do something like creating ASCII strings from all the data-values, with the downside that this will create quite a bit of data-bloat. There are other cross-platform standards for serialized data such as JSON, SOAP, etc.

Jason
  • 31,834
  • 7
  • 59
  • 78