Thread: Help with UDP Server/Client Program

  1. #1
    Registered User
    Join Date
    Mar 2010
    Posts
    4

    Question Help with UDP Server/Client Program

    I am trying to set this up so that when the client makes a connection with the server, the server will send the current time back to the client, and the client will display it. I'm having a few problems.

    *NOTE* I have edited both programs a bit, but I am getting an error message when trying to compile UDPServer. It is as follows ---
    UDPServer.c: In function âSIGIOHandlerâ:
    UDPServer.c:97: warning: passing argument 2 of âsendtoâ makes pointer from integer without a cast
    UDPServer.c:100: error: expected âwhileâ before â}â token

    I really am at a loss with all of this. Any help will be greatly appreciated.

    UDPServer.c
    Code:
    #include <stdio.h>      /* for printf() and fprintf() */
    #include <sys/socket.h> /* for socket(), bind, and connect() */
    #include <arpa/inet.h>  /* for sockaddr_in and inet_ntoa() */
    #include <stdlib.h>     /* for atoi() and exit() */
    #include <string.h>     /* for memset() */
    #include <unistd.h>     /* for close() and getpid() */
    #include <fcntl.h>      /* for fcntl() */
    #include <sys/file.h>   /* for O_NONBLOCK and FASYNC */
    #include <signal.h>     /* for signal() and SIGALRM */
    #include <errno.h>      /* for errno */
    #include <time.h>	/* for time */
    
    #define ECHOMAX 255     /* Longest string to echo */
    
    void DieWithError(char *errorMessage);  /* Error handling function */
    void UseIdleTime();                     /* Function to use idle time */
    void SIGIOHandler(int signalType);      /* Function to handle SIGIO */
    
    int sock;                        /* Socket -- GLOBAL for signal handler */
    
    int main(int argc, char *argv[])
    {
        struct sockaddr_in echoServAddr; /* Server address */
        unsigned short echoServPort;     /* Server port */
        struct sigaction handler;        /* Signal handling action definition */
    
        /* Test for correct number of parameters */
        if (argc != 2)
        {
            fprintf(stderr,"Usage:  %s <SERVER PORT>\n", argv[0]);
            exit(1);
        }
    
        echoServPort = atoi(argv[1]);  /* First arg:  local port */
    
        /* Create socket for sending/receiving datagrams */
        if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
            DieWithError("socket() failed");
    
        /* Set up the server address structure */
        memset(&echoServAddr, 0, sizeof(echoServAddr));   /* Zero out structure */
        echoServAddr.sin_family = AF_INET;                /* Internet family */
        echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
        echoServAddr.sin_port = htons(echoServPort);      /* Port */
    
        /* Bind to the local address */
        if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
            DieWithError("bind() failed");
    
        /* Set signal handler for SIGIO */
        handler.sa_handler = SIGIOHandler;
        /* Create mask that mask all signals */
        if (sigfillset(&handler.sa_mask) < 0) 
            DieWithError("sigfillset() failed");
        /* No flags */
        handler.sa_flags = 0;
    
        if (sigaction(SIGIO, &handler, 0) < 0)
            DieWithError("sigaction() failed for SIGIO");
    
        /* We must own the socket to receive the SIGIO message */
        if (fcntl(sock, F_SETOWN, getpid()) < 0)
            DieWithError("Unable to set process owner to us");
    
        /* Arrange for nonblocking I/O and SIGIO delivery */
        if (fcntl(sock, F_SETFL, O_NONBLOCK | FASYNC) < 0)
            DieWithError("Unable to put client sock into non-blocking/async mode");
    
        /* Go off and do real work; echoing happens in the background */
    
        for (;;)
            UseIdleTime();
    
        /* NOTREACHED */
    }
    
    void UseIdleTime()
    {
        printf(".\n");
        sleep(3);     /* 3 seconds of activity */
    }
    
    void SIGIOHandler(int signalType)
    {
        time_t currentTime;
        struct sockaddr_in echoClntAddr;  /* Address of datagram source */
        unsigned int clntLen;             /* Address length */
    
        do  /* As long as there is input... */
        {
            /* Set the size of the in-out parameter */
            clntLen = sizeof(echoClntAddr);
    
                printf("Handling client %s\n", inet_ntoa(echoClntAddr.sin_addr));
    
                if (sendto(sock, currentTime, sizeof(currentTime), 0, (struct sockaddr *) 
                      &echoClntAddr, sizeof(echoClntAddr)) != sizeof(currentTime))
                    DieWithError("sendto() failed");
            }
        }  while (sizeof(currentTime) >= 0);
        /* Nothing left to receive */
    }
    UDPClient.c
    Code:
    #include <stdio.h>      /* for printf() and fprintf() */
    #include <sys/socket.h> /* for socket(), connect(), sendto(), and recvfrom() */
    #include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
    #include <stdlib.h>     /* for atoi() and exit() */
    #include <string.h>     /* for memset() */
    #include <unistd.h>     /* for close() and alarm() */
    #include <errno.h>      /* for errno and EINTR */
    #include <signal.h>     /* for sigaction() */
    
    #define BUFFERMAX         255     /* Longest string to receive */
    #define TIMEOUT_SECS    2       /* Seconds between retransmits */
    #define MAXTRIES        5       /* Tries before giving up */
    
    int tries=0;   /* Count of times sent - GLOBAL for signal-handler access */
    
    void DieWithError(char *errorMessage);   /* Error handling function */
    void CatchAlarm(int ignored);            /* Handler for SIGALRM */
    
    int main(int argc, char *argv[])
    {
        int sock;                        /* Socket descriptor */
        struct sockaddr_in echoServAddr; /* Echo server address */
        struct sockaddr_in fromAddr;     /* Source address of echo */
        unsigned short echoServPort;     /* Echo server port */
        unsigned int fromSize;           /* In-out of address size for recvfrom() */
        struct sigaction myAction;       /* For setting signal handler */
        char *servIP;                    /* IP address of server */
        char timeBuffer[BUFFERMAX+1];      /* Buffer for echo string */
        int timeStringLen;               /* Length of string to echo */
        int respStringLen;               /* Size of received datagram */
    
        if ((argc < 2) || (argc > 3))    /* Test for correct number of arguments */
        {
            fprintf(stderr,"Usage: %s <Server IP> [<Echo Port>]\n", argv[0]);
            exit(1);
        }
    
        servIP = argv[1];           /* First arg:  server IP address (dotted quad) */
    
        if (argc == 3)
            echoServPort = atoi(argv[2]);  /* Use given port, if any */
        else
            echoServPort = 7;  /* 7 is well-known port for echo service */
    
        /* Create a best-effort datagram socket using UDP */
        if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
            DieWithError("socket() failed");
    
        /* Set signal handler for alarm signal */
        myAction.sa_handler = CatchAlarm;
        if (sigfillset(&myAction.sa_mask) < 0) /* block everything in handler */
            DieWithError("sigfillset() failed");
        myAction.sa_flags = 0;
    
        if (sigaction(SIGALRM, &myAction, 0) < 0)
            DieWithError("sigaction() failed for SIGALRM");
    
        /* Construct the server address structure */
        memset(&echoServAddr, 0, sizeof(echoServAddr));    /* Zero out structure */
        echoServAddr.sin_family = AF_INET;
        echoServAddr.sin_addr.s_addr = inet_addr(servIP);  /* Server IP address */
        echoServAddr.sin_port = htons(echoServPort);       /* Server port */
      
        /* Get a response */
        fromSize = sizeof(fromAddr);
        alarm(TIMEOUT_SECS);        /* Set the timeout */
        while ((respStringLen = recvfrom(sock, timeBuffer, BUFFERMAX, 0,
               (struct sockaddr *) &fromAddr, &fromSize)) < 0)
            if (errno == EINTR)     /* Alarm went off  */
            {
                if (tries < MAXTRIES)      /* incremented by signal handler */
                {
                    printf("timed out, %d more tries...\n", MAXTRIES-tries);
                    alarm(TIMEOUT_SECS);
                } 
                else
                    DieWithError("No Response");
            } 
            else
                DieWithError("recvfrom() failed");
    
        /* recvfrom() got something --  cancel the timeout */
        alarm(0);
    
        /* null-terminate the received data */
        timeBuffer[respStringLen] = '\0';
        printf("Received: %s\n", timeBuffer);    /* Print the received data */
        
        close(sock);
        exit(0);
    }
    
    void CatchAlarm(int ignored)     /* Handler for SIGALRM */
    {
        tries += 1;
    }
    DieWithError.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    void DieWithError(char *errorMessage)
    {
    perror(errorMessage);
    exit(1);
    }
    Last edited by handsomedan; 03-23-2010 at 09:38 PM.

  2. #2
    Registered User
    Join Date
    Feb 2010
    Posts
    26
    Remove the curly brace in udpserver.c in the following line.
    Code:
     }  while (sizeof(currentTime) >= 0);
    Remove the curly brace ('}') in the above line.
    Then in the sendto function pass the address of currenttime.
    Your code,
    Code:
    if (sendto(sock,currentTime, sizeof(currentTime), 0, (struct sockaddr *)
    Change it like the following.

    Code:
    if (sendto(sock, &currentTime, sizeof(currentTime), 0, (struct sockaddr *)
    Last edited by kiruthika; 03-23-2010 at 10:31 PM.

  3. #3
    Registered User
    Join Date
    Mar 2010
    Posts
    4
    I have altered my code to with your suggestions, but now I can't seem to get them to connect. They connected fine before I tried changing it a little.

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by handsomedan View Post
    I have altered my code to with your suggestions, but now I can't seem to get them to connect. They connected fine before I tried changing it a little.
    Something suspicious here:

    UDPServer.c: In function âSIGIOHandlerâ:
    UDPServer.c:97: warning: passing argument 2 of âsendtoâ makes pointer from integer without a cast
    UDPServer.c:100: error: expected âwhileâ before â}â token
    An error means your code was not compiled, so it is impossible that "they connected fine before" -- probably you have a previous version of the executable, and you have been assuming that was the latest one. However, if the code did not compile because of errors, then that old executable was not produced from the code you posted.

    After you removed the error, the code did compile, so now you have a new executable. Make sense? kiruthika is correct about both issues. The problem with your code is more significant; unfortunately you have been led astray believing you were compiling and testing the code as you wrote it, when in fact it was never being compiled, so you were testing the same (old) program over and over while you added to the code.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    Mar 2010
    Posts
    4
    I'm sorry. I have corrected those two errors, and yes, I have been able to compile the new programs. I guess I should have corrected them up there in my code. It does run, but they just can't seem to make a connection.

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    I've done a bunch of tcp server clients but never a udp one, so I probably can't help much.

    I will say that networking stuff always seems to require a silly amount of debugging to get right. I'd just start throwing in a lot of:
    Code:
    fprintf(stderr, "....
    until you get to the bottom of it.

    My usual approach with the printf debugging statements is to not indent them so they are easy to find and comment out or remove. Then when I first think I'm done with it, I move it to the bottom of the page:
    Code:
    /* 
    fprintf(stderr, [sometimes long set of variables to report and format readably]
    */
    in case I turn out to need them again.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Using select() for client UDP
    By jazzman83 in forum C Programming
    Replies: 2
    Last Post: 04-03-2007, 05:31 AM
  2. simultaneously waiting for data on FIFO and UDP using select call
    By yogesh3073 in forum Networking/Device Communication
    Replies: 2
    Last Post: 01-05-2007, 09:53 AM
  3. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  4. My program, anyhelp
    By @licomb in forum C Programming
    Replies: 14
    Last Post: 08-14-2001, 10:04 PM