0

I got a segmentation fault problem when I write a client-server project in UDP. It happens on server side, when I receive a packet from client and going to send an ACK back. I tried to search the solutions and got UDP Server giving Segmentation Fault and C concurrent UDP socket , weird segmentation fault, but seems both of those are not the answer I'm looking for.

Here is my server side code

#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

   }
}

I'm not really good at C, so forgive me if the code is silly. Please point out anything wrong or just looks weird. Thanks in advance for any help.

Community
  • 1
  • 1
EricBkc
  • 369
  • 2
  • 4
  • 12

1 Answers1

1

pkt is pointer to a Pkt, but you haven't initialized it. Likewise with ack. You can either a) malloc a Pkt and assign the result to pkt, or b) change pkt to be a Pkt structure (rather than a pointer). The second option would look something like:

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);
keithmo
  • 4,893
  • 1
  • 21
  • 17
  • Thanks the answer. But I'm not fully understand about the "initialized" part. Does this mean I should clean the struct buffer before I re-use it? And what if I use malloc? – EricBkc Nov 22 '15 at 05:30
  • Consider `int foo; printf("%d", foo);` -- what value will be printed? Accessing the value of `foo` before assigning a value to is is considered "undefined behavior". Accessing it could return a semi-random garbage value (likely), it could crash the program, or it could format your hard drive (extremely unlikely, but this seems to be the canonical example of bad things that can happen when venturing into "undefined behavior"). Now consider `int foo = 3; printf("%d", foo);` -- This will always print '3', because foo is now initialized (with the value 3). (cont) – keithmo Nov 22 '15 at 06:02
  • Now consider `struct Pkt* pkt;` -- `pkt` is a pointer, but where does it point? Until it's value is set, it's undefined. Calling `recv()` with an uninitialized pointer as the buffer can crash the app, corrupt critical memory, or format your hard drive (see above). – keithmo Nov 22 '15 at 06:06
  • http://stackoverflow.com/questions/11962457/why-is-using-an-uninitialized-variable-undefined-behavior-in-c has better explanations of undefined behavior caused by accessing uninitialized variables. – keithmo Nov 22 '15 at 06:11