2015-11-22 3 views
0

У меня возникла проблема с сегментацией при написании проекта клиент-сервер в UDP. Это происходит на стороне сервера, когда я получаю пакет от клиента и отправляю ACK обратно. Я попытался найти решения и получил UDP Server giving Segmentation Fault и C concurrent UDP socket , weird segmentation fault, но, похоже, оба из них не являются ответом, который я ищу.Ошибка сегментации в UDP

Вот мой код

#include <ctype.h>   /* for toupper */ 
#include <stdio.h>   /* for standard I/O functions */ 
#include <stdlib.h>   /* for exit */ 
#include <string.h>   /* for memset */ 
#include <sys/socket.h>  /* for socket, sendto, and recvfrom */ 
#include <netinet/in.h>  /* for sockaddr_in */ 
#include <unistd.h>   /* for close */ 

#define STRING_SIZE 1024 

#define SERV_UDP_PORT 12311 



int main(void) { 

    int sock_server; 

    struct sockaddr_in server_addr; 

    unsigned short server_port; 

    struct sockaddr_in client_addr; 

    unsigned int client_addr_len; 

    char sentence[STRING_SIZE]; 

    char modifiedSentence[STRING_SIZE]; 

    unsigned int msg_len; 

    int bytes_sent, bytes_recd; 

    unsigned int i; 

    struct Pkt 
    { 
    short length; 
    short seqnum; 
    char databytes[80]; 
    }; 
    struct Pkt* pkt; 

    int j ;  //for loop 
    int seq; 
    short num_of_bytes; 
    //char ack_num[2]; 


    struct Ack 
    { 
    short ack_num; 
    }; 
    struct Ack* ack; 




    /* open a socket */ 

    if ((sock_server = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 
     perror("Server: can't open datagram socket\n"); 
     exit(1); 
    } 

    /* initialize server address information */ 

    memset(&server_addr, 0, sizeof(server_addr)); 
    server_addr.sin_family = AF_INET; 
    server_addr.sin_addr.s_addr = htonl (INADDR_ANY); 
    server_port = SERV_UDP_PORT; 
    server_addr.sin_port = htons(server_port); 

    /* bind the socket to the local server port */ 

    if (bind(sock_server, (struct sockaddr *) &server_addr, 
            sizeof (server_addr)) < 0) { 
     perror("Server: can't bind to local address\n"); 
     close(sock_server); 
     exit(1); 
    } 

    /* wait for incoming messages in an indefinite loop */ 

    printf("Waiting for incoming messages on port %hu\n\n", 
          server_port); 

    client_addr_len = sizeof (client_addr); 

    for (;;) { 

     bytes_recd = recvfrom(sock_server, pkt, sizeof(*pkt), 0, (struct sockaddr *) &client_addr, &client_addr_len); 

     ack->ack_num = pkt->seqnum; 
     printf("%02d\n", ack->ack_num); 
     num_of_bytes = pkt->length; 
     printf("The sequence number is: %d\n", ack->ack_num); 
     printf("Received Sentence is: %s\n  with length %d\n\n", pkt->databytes, num_of_bytes); 
     msg_len = 3; 


     /* send message */ 

     bytes_sent = sendto(sock_server, (struct Ack*)&ack, msg_len, 0, (struct sockaddr*) &client_addr, client_addr_len);  //Here is the segmentation fault comes from 

    } 
} 

стороне сервера я не очень хорошо на C, так что простите меня, если код глупо. Просьба указать на что-то неправильное или просто выглядит странно. Заранее благодарим за любую помощь.

ответ

1

pkt является указателем на Pkt, но вы его не инициализировали. Аналогично с ack. Вы можете: a) malloc a Pkt и присвоить результат pkt, или b) изменить pkt как структуру Pkt (а не указатель). Второй вариант будет выглядеть примерно так:

struct Pkt pkt; 
struct Ack ack; 

bytes_recd = recvfrom(sock_server, &pkt, sizeof(pkt), 0, (struct sockaddr *) &client_addr, &client_addr_len); 

ack.ack_num = pkt.seqnum; 
printf("%02d\n", ack.ack_num); 
num_of_bytes = pkt.length; 
printf("The sequence number is: %d\n", ack.ack_num); 
printf("Received Sentence is: %s\n  with length %d\n\n", pkt.databytes, num_of_bytes); 

/* send message */ 

bytes_sent = sendto(sock_server, &ack, sizeof(ack), 0, (struct sockaddr*) &client_addr, client_addr_len); 
+0

Спасибо, ответ. Но я не совсем понимаю о «инициализированной» части. Означает ли это, что я должен очистить буфер структуры до того, как его повторно использовать? А что, если я использую malloc? – EricBkc

+0

Рассмотрим 'int foo; printf ("% d", foo); '- какое значение будет напечатано? Доступ к значению 'foo' перед присвоением значения is считается« неопределенным поведением ». Доступ к нему может вернуть полузасушливое значение мусора (вероятно), это может привести к сбою программы или может форматировать ваш жесткий диск (крайне маловероятно, но это, по-видимому, канонический пример плохих вещей, которые могут произойти, когда вы идете в «неопределенные поведение"). Теперь рассмотрим 'int foo = 3; printf ("% d", foo); '- это всегда будет печатать '3', потому что foo теперь инициализируется (со значением 3). (cont) – keithmo

+0

Теперь рассмотрим 'struct Pkt * pkt;' - 'pkt' - это указатель, но где он указывает? Пока значение не будет установлено, оно не определено. Вызов 'recv()' с неинициализированным указателем, поскольку буфер может привести к сбою приложения, повреждению критической памяти или форматированию жесткого диска (см. Выше). – keithmo

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