Thread: socket program:using the read() instead of recv()

  1. #1
    Registered User
    Join Date
    Mar 2008
    Location
    India
    Posts
    147

    socket program:using the read() instead of recv()

    hello all,

    i have simple udp server program as followed.

    Code:
    #cat ex_4.c 
    /*a UDP serve program. This program creates a socket and binds to a port address given by the user. Now before reading the socket for any message from client, it takes the number of bytes to read, from the user.Then it uses the read() system call to read the message from the client.The third argument to read() is the number of bytes specified by the user.After reading any message , it simply displays the message and again asks the user to give size of message.This continues in a forever loop. 
     */
    
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MAX_MSG 100
    
    void toggleCase(char* mesg,int cnt);
    
    void errExit(char *str)
    {
         puts(str);
         exit(0);
    }
    
    int main()
    {
         int sockFd;
         struct sockaddr_in srvAdr, cliAdr;
         int cliLen,n;
         int portNo,noOfBytes;
         char mesg[MAX_MSG];
    
         printf("Enter the server port number \n");
         scanf("%d",&portNo);
    
         if((sockFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    	  errExit("Can't open datagram socket\n");
    
         memset(&srvAdr, 0, sizeof(srvAdr));
         srvAdr.sin_family = AF_INET;
         srvAdr.sin_addr.s_addr = htonl(INADDR_ANY);
         srvAdr.sin_port = htons(portNo);
    
         if(bind(sockFd,(struct sockaddr*)&srvAdr, sizeof(srvAdr)) < 0)
    	  errExit("Can't bind local address \n");
    
         printf("Server waiting for messages \n");
    
         while(1)
         {
    	  printf("Enter number of bytes to read from the client.\n");
    	  scanf("%d",&noOfBytes);
    	  
    	  cliLen = sizeof(cliAdr);
    
    	  n = read(sockFd, &mesg, noOfBytes);
    
    	  mesg(noOfBytes+1) = '\0';
    
    	  if(n < 0)
    	       errExit("recv from");
    	  
    	  toggleCase(mesg,n);
    	  
    	  printf("Received following message from client %s\n",mesg);
         }
    
         close(sockFd);
    }
    
    
    void toggleCase(char *buf,int cnt)
    {
         int ii;
         
         for(ii=0;ii<cnt;ii++)
         {
    	  if(buf[ii] >= 'A' && buf[ii] <= 'Z')
    	       buf[ii] += 0x20;
    	  else if(buf[ii] >= 'a' && buf[ii] <= 'z')
    	       buf[ii] -= 0x20;
         }
    }
    Here when i read number of bytes using read i even see some junk message on my console as
    below along with the message which i sent . i you see i get junk after "J".

    output
    --------

    ./ex4
    Enter the server port number
    8000
    Server waiting for messages
    Enter number of bytes to read from the client.
    10
    Received following message from client ABCDEFGHIJ��܁T\��\ڜ



    why am i seeing this

    iam using following as my udp client to send messages.

    Code:
    $ cat ex_3.c
    /* 
    UDP client program developed in exercise 2 has some limitation.If server program does not send a response .The client program will block and never exits.So with the help of select() seystem implement a timeout feature(You may do this exercise only after select() system call is covered in the class).
     */
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <curses.h>
    
    #define MAX_MSG 100
    #define TIMEOUT 5
    
    void errExit(char *str)
    {
         puts(str);
         exit(0);
    }
    
    int main()
    {
         int sockFd;
         struct timeval tv;
         struct sockaddr_in srvAdr;
         char txmsg[MAX_MSG];
         char rxmsg[MAX_MSG];
         char serverIpAddress[32];
         int serverPortNo = 0;
         fd_set readfds;
         int n;
         int ret;
         
         memset(serverIpAddress,0,sizeof(serverIpAddress));
    
         if((sockFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    	  errExit("Can't open datagram socket\n");
    
         printf("Enter the server ip address and port no");
         scanf("%s %d\n",serverIpAddress,&serverPortNo);
    
         memset(&srvAdr, 0, sizeof(srvAdr));
         srvAdr.sin_family = AF_INET;
         srvAdr.sin_addr.s_addr = inet_addr(serverIpAddress);
         srvAdr.sin_port = htons(serverPortNo);
    
         fflush(stdin);
         printf("Enter message to send\n");
         fgets(txmsg,MAX_MSG,stdin);
    
         n = strlen(txmsg) + 1;
    
         if(sendto(sockFd,txmsg,n,0,(struct sockaddr *)&srvAdr,sizeof(srvAdr)) != n)
    	  errExit("send to error\n");
    
    
         close(sockFd);
    }

    input
    ----
    ./ex3
    Enter the server ip address and port no127.0.0.1 8000
    abcdefghijklmnopqrst
    Enter message to send



    here another dobut , even though i kept a fflush on stdin to print "enter message to send" either it takes "\n" as input or it waits to get it printed after i enter the message as you can see in my input.

    please let me know your comments where am i missing .

  2. #2
    Registered User
    Join Date
    Nov 2004
    Location
    USA
    Posts
    516
    It should be :
    Code:
    mesg[n] = '\0';
    You should not fflush() input streams. You should ideally clear it using getchar(). Check the FAQ on how to clear stdin.
    Last edited by PING; 05-17-2011 at 06:39 PM.
    Code:
    >+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++.

  3. #3
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Read is not null terminating strings the way recv() would.

    Code:
      mesg(noOfBytes+1) = '\0';
    I'm surprised your compiler didn't complain about this... it should be

    Code:
      mesg[noOfBytes+1] = '\0';
    Last edited by CommonTater; 05-17-2011 at 06:40 PM.

  4. #4
    Registered User
    Join Date
    Mar 2008
    Location
    India
    Posts
    147
    thx , i overlooked the [] and kept it ().

    any guess why my client program it not does print the message "Enter message to send" untill i press enter.

    I know that in scanf iam waiting for \n.

    but i do not wait for that the fgets in the client is taking \n as input and programing is getting terminated.

    I want it print the message and then wait for the message. can i do this using fgets.

  5. #5
    Registered User
    Join Date
    Jun 2010
    Location
    In a house
    Posts
    15
    I'm surprised your compiler didn't complain about this... it should be

    Code:
      mesg[noOfBytes+1] = '\0';

    mesg[noOfBytes] = '\0'; is more appropriate.

  6. #6
    Registered User
    Join Date
    Nov 2004
    Location
    USA
    Posts
    516
    Actually, the correct thing would be mesg[n] as read() might return a value less than noBytes. Don't try to capture the \n in scanf().
    Code:
    scanf();
    //gobble up all \ns
    printf();
    fgets();
    should work.
    Code:
    >+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++.

  7. #7
    Registered User
    Join Date
    Mar 2008
    Location
    India
    Posts
    147
    If i remove \n in scanf, consoloe is not waiting for the message input.
    It is conisdering \n as input for the message and executing.

    Code:
      printf("Enter the server ip address and port no");
         scanf("%s %d",serverIpAddress,&serverPortNo);
    
         fflush(stdin);
         printf("Enter message to send\n");
         fgets(txmsg,MAX_MSG,stdin);
    output/input while executing is:

    ./ex3
    Enter the server ip address and port no127.0.0.1 8000\n
    Enter message to send

    this is end of program.

  8. #8
    Registered User
    Join Date
    Nov 2004
    Location
    USA
    Posts
    516
    As I said, fflush(stdin) is wrong as behavior of fflush() with input streams results in undefined behavior. You need to gobble up the '\n's. You can simply put a getchar() in your scenario in place of the stdin() for your code to work.
    Code:
    >+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++.

  9. #9
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Ping means like this....

    Code:
      printf("Enter the server ip address and port no");
         scanf("%s %d",serverIpAddress,&serverPortNo);
    
         // fflush(stdin);   <-- bad, evil, ugly
       
         getchar();
    
         printf("Enter message to send\n");
         fgets(txmsg,MAX_MSG,stdin);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Avoiding program blocking while recv()
    By trooper in forum Networking/Device Communication
    Replies: 2
    Last Post: 04-05-2011, 04:22 AM
  2. blocked on read/recv / how to read/send proper buffers
    By fudgecode in forum Networking/Device Communication
    Replies: 1
    Last Post: 11-02-2010, 11:42 PM
  3. help with socket send/recv
    By ac251404 in forum Networking/Device Communication
    Replies: 10
    Last Post: 06-29-2006, 07:32 PM
  4. recv on nonblocking socket
    By l2u in forum Networking/Device Communication
    Replies: 4
    Last Post: 05-20-2006, 07:02 PM
  5. socket programming recv function
    By vicky in forum Linux Programming
    Replies: 2
    Last Post: 10-29-2001, 03:39 AM