Md. Talha
Md. Talha

Reputation: 1

Problem in udp socket programing in c

I complile the following C code of UDP client after I run './udpclient localhost 9191' in terminal.I put "Enter Text= " as Hello, but it is showing error in sendto as below:

Enter text: hello 
hello
 : error in sendto()guest-1SDRJ2@md-K42F:~/Desktop$ 

"

Note: I open 1st the server port as below in other terminal ./server 9191. I beleive there is no error in server code. The udp client is not passing message to server. If I don't use thread , the message is passing .But I have to do it by thread.

UDP client Code:

/* simple UDP echo client */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <pthread.h>

#define STRLEN 1024

static void *readdata(void *);
static void *writedata(void *);
  int sockfd, n, slen;
struct sockaddr_in servaddr;
char sendline[STRLEN], recvline[STRLEN];

int main(int argc, char *argv[]) {
  pthread_t  readid,writeid;

  struct sockaddr_in servaddr;
  struct hostent *h;

  if(argc != 3) {
    printf("Usage: %s <proxy server ip> <port>\n", argv[0]);
    exit(0);
  }

  /* create hostent structure from  user entered host name*/
  if ( (h = gethostbyname(argv[1])) == NULL) {
    printf("\n%s: error in gethostbyname()", argv[0]);
    exit(0);
  }

  /* create server address structure */
  bzero(&servaddr, sizeof(servaddr)); /* initialize it */
  servaddr.sin_family = AF_INET;
  memcpy((char *) &servaddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
  servaddr.sin_port = htons(atoi(argv[2])); /* get the port number from argv[2]*/

  /* create a UDP socket: SOCK_DGRAM */
  if ( (sockfd = socket(AF_INET,SOCK_DGRAM, 0)) < 0) {
    printf("\n%s: error in socket()", argv[0]);
    exit(0);
  }


  pthread_create(&readid,NULL,&readdata,NULL);
  pthread_create(&writeid,NULL,&writedata,NULL);

  while(1)
  {
  };

  close(sockfd);
}

static void * writedata(void *arg)
 {
 /* get user input */
  printf("\nEnter text: ");

  do {
      if (fgets(sendline, STRLEN, stdin) == NULL) {
        printf("\n%s: error in fgets()");
        exit(0);
      }
      /* send a text */
      if (sendto(sockfd, sendline, sizeof(sendline), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
          printf("\n%s: error in sendto()");
          exit(0);
      }
     }while(1);
}

static void * readdata(void *arg)
{
  /* wait for echo */
  slen = sizeof(servaddr);
  if ( (n = recvfrom(sockfd, recvline, STRLEN, 0, (struct sockaddr *) &servaddr, &slen)) < 0) {
      printf("\n%s: error in recvfrom()");
      exit(0);
  }

  /* null terminate the string */
  recvline[n] = 0;

  fputs(recvline, stdout);


}

Upvotes: 0

Views: 729

Answers (1)

Chris Dodd
Chris Dodd

Reputation: 126536

The problem is that you're using the same sockaddr struct (servaddr) for both the sendto and revfrom calls. The recvfrom happens first, so it clears out servaddr in preparation for writing in the source address of the received packed (once it receives one -- that thread is still blocked in the kernel waiting for a packet). Then, when the sendto call occurs, the sockaddr is all zeros, so it immediately returns EINVAL.

You may be getting confused by the fact that the sockaddr argument to recvfrom is an OUTPUT, not an input -- it gets filled in with the source address of the packet that is received (which could be from anywhere). If you want to only receive packets from a particular place (the server?), you need to check the address after the recvfrom returns and toss the packet if it comes from somewhere else, looping back to recvfrom again.

Upvotes: 1

Related Questions