2015-12-27 2 views
-2

Вот моего отправитель код стороныНевозможно получить полный целочисленный массив через UDP сокет в C

void send_data(int port, int coords[4]){ 

    struct sockaddr_in si_me, si_other; 
    int s, i, slen = sizeof(si_other), recv_len; 
    char buf[BUFLEN]; 

    //create a UDP socket 
    if((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){ 
     err_print("socket"); 
    } 

    //zero out the structure 
    memset((char*)&si_me, 0, sizeof(si_me)); 

    si_me.sin_family = AF_INET; 
    si_me.sin_port = htons(port); 
    si_me.sin_addr.s_addr = htonl(INADDR_ANY); 

    //bind socket to the port 
    if(bind(s, (struct sockaddr *)&si_me, sizeof(si_me)) == -1){ 
     err_print("bind"); 
    } 
    int size = sizeof(coords); 
    printf("Size: %d\n", size); 
    //Keep listening for data 
    while(1){ 
     printf("Waiting for Data\n"); 
     fflush(stdout); 

     memset(buf, 0, BUFLEN); 
     //try to receive some data, this is a blocking call 
     if((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr*) &si_other, &slen)) == -1){ 
      err_print("recvfrom()"); 
     } 

     //print details of the client/peer and the data received 
     printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); 
     printf("%s\n", buf); 

     if(!strcmp(buf, "coords")) { 

      printf("Sending Coordinates: \n"); 
      //now reply the client with the same data 
      int siz = sendto(s, coords, sizeof(coords), 0, (struct sockaddr*) &si_other, slen); 
      if(siz == -1){ 
       err_print("sendto()"); 
      } 
      printf("Siz: %d\n", siz); 

      } 

      break; 
     } 

    } 

    close(s); 
} 

Значение, возвращенная из SendTo 8, который является правильным размером целочисленного массива, но на стороне приемника recvfrom возвращает 0 хотя массив получает первые два целочисленных элемента, а остальные - значения мусора, когда я печатаю массив. Вот код на стороне приемника:

void get_data(int port, int coords[]){ 

    struct sockaddr_in si_other; 

    int s, i; 
    char message[BUFLEN]; 

    if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){ 
     err_print("socket"); 
    } 

    memset((char*)&si_other, 0, sizeof(si_other)); 
    si_other.sin_family = AF_INET; 

    si_other.sin_port = htons(port); 
    si_other.sin_addr.s_addr = inet_addr(SERVER); 

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

    socklen_t slen = sizeof(si_other); 


    int size = sizeof(coords); 
    printf("Size: %d\n", size); 
    int siz = 0; 
    while(1) 
    { 
     printf("Enter message : "); 
     strcpy(message, "coords"); 

     //send the message 
     if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen)==-1) 
     { 
      err_print("sendto()"); 
     } 

     //try to receive some data, this is a blocking call 

     if (siz = (recvfrom(s, coords, 8, 0, (struct sockaddr *) &si_other, &slen)) == -1) 
     { 
      err_print("recvfrom()"); 
     } 
     printf("Siz: %d\n", siz); 

     break; 
    } 

    for(int j = 0; j<4; j++){ 
     printf("C: %d\n", coords[j]); 
    } 



    close(s);  

    return; 
} 

И выход координат массива на стороне приемника: 1 2 4196592 0 Теперь, я думал, что, может быть, весь массив не был послан, но значения размера возвращаемого SendTo равно 8, а значение recvfrom равно 0, даже если оно получает первые два элемента вправо. Кроме того, обратите внимание, что при компиляции я получаю предупреждение для sizeof: 'sizeof' по параметру функции массива 'coords' будет возвращать размер 'int *'

Что может быть неправильным здесь и каким правильным способом отправить массив? И если возможно, может быть отправлен двойной массив?

+0

Вы устанавливаете 'slen = sizeof (si_other)' перед вызовом 'recvfrom()'? – keithmo

+1

Вопросы поиска справки по отладке («почему этот код не работает?») Должны включать в себя желаемое поведение, конкретную проблему или ошибку и кратчайший код, необходимый для воспроизведения в самом вопросе. Вопросы без четкого описания проблемы не полезны другим читателям. См.: Как создать минимальный, полный и проверенный пример. – Olaf

+1

Если 'sizeof (coords)' is '8' на платформе отправки, что означает' sizeof (int) '' 2', то есть 16 бит. В наши дни это распространено только на небольших встроенных платформах, на обычном современном ПК 'sizeof (int)' обычно '4'. Если вы отправляете и получаете на разных платформах, вы должны использовать [целые числа фиксированной ширины] (http://en.cppreference.com/w/c/types/integer), чтобы удостовериться, что обе стороны отправки и получения имеют одинаковый размер. Также будьте осторожны с проблемами [endianness] (https://en.wikipedia.org/wiki/Endianness). –

ответ

2

Ключом здесь является утверждение в вопросе является то, что SizeOf (Coords), 4-элементный int массив а, приводит 8.

Это было бы только в том случае, если, конечно, на этой реализации SizeOf (int) равно 2. Я полагаю, что 16-битные платформы не совсем неслыханны в наши дни, особенно во встроенных пространствах. Но затем после этого утверждается, что печать int также приводит к 4196592, что, конечно, не может быть в случае двухбайтового int.

Единственное объяснение заключается в том, что приведенный здесь пример не содержит ключевой информации. Код, который вызывает sendfrom(), не имеет прямого доступа к массиву coords. Скорее всего, массив coords передается в качестве параметра этой функции. Который, конечно же, превращает его в int *, причем его sizeof составляет 8, в результате чего только первые два байта числа int отправляются через сокет. Это также объяснение предупреждения компилятора.

Кто знает, что происходит на стороне приема.

+0

Да. Я передал координаты в качестве параметра. Это может быть проблемой, но это не объясняет, почему recvfrom возвращает 0. –

+0

Даже если вы отправляете нужный объем данных, вы * должны * читать из сокета в цикле, пока не прочтете все нужные данные. Вы * не * гарантированно получаете все данные за один вызов, чтобы возвратиться. –

+0

Да. Согласен. Но recvfrom возвращает значение 0, а не даже 2 или 4, даже если он получил два элемента. Я также думал о цикле, но как размер может быть равен нулю, даже если он получил два элемента. –