/* * udp.c * * Author: Erich Styger * License: PDX-License-Identifier: BSD-3-Clause * * UDP example code by Paul Krzyzanowski, see * https://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html */ #include #include #include #include #include #include #include #include "hostname.h" #include "platform.h" #define BUFSIZE (64) int udp_receive(int port) { struct sockaddr_in myaddr; /* our address */ struct sockaddr_in remaddr; /* remote address */ socklen_t addrlen = sizeof(remaddr); /* length of addresses */ int recvlen; /* # bytes received */ int fd; /* our socket */ int msgcnt = 0; /* count # of messages we received */ static unsigned char buf[BUFSIZE]; /* receive buffer */ /* create a UDP socket */ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("cannot create socket\n"); return 0; } /* bind the socket to any valid IP address and a specific port */ memset((char *)&myaddr, 0, sizeof(myaddr)); myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = htonl(INADDR_ANY); myaddr.sin_port = htons(port); if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { perror("bind failed"); return 0; } /* now loop, receiving data and printing what we received */ for (;;) { printf("waiting on port %d\n", port); recvlen = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&remaddr, &addrlen); if (recvlen > 0) { buf[recvlen] = 0; printf("received message: \"%s\" (%d bytes)\n", buf, recvlen); } else { printf("uh oh - something went wrong!\n"); } sprintf((char*)buf, "ack %d", msgcnt++); printf("sending response \"%s\"\n", buf); if (sendto(fd, buf, strlen((char*)buf), 0, (struct sockaddr *)&remaddr, addrlen) < 0) { perror("sendto"); } } /* never exits */ } /* send a UDP datagram. Parameters are strings, e.g. * host IP, e.g. "10.180.254.51" * port number, e.g. "1234" * msg message string to send, e.g. "hello" * \return negative value in case of failure */ int udp_send(const char *host, int port, const char *msg) { struct sockaddr_in myaddr, remaddr; int fd, i; socklen_t slen=sizeof(remaddr); static char buf[BUFSIZE]; /* message buffer */ int recvlen; /* # bytes in acknowledgement message */ int portNumber; char ipBuf[64]; /* in case 'host' is a hostname and not an IP address, this will hold the IP address */ /* hostname to IP transformation */ if (*host >='0' && *host<='9') { /* IP address */ printf("IP: %s\n", host); } else { if (hostname_to_ip(host, ipBuf, sizeof(ipBuf))==0) { printf("hostname '%s' -> IP: '%s'\n", host, ipBuf); host = ipBuf; /* point to transformed IP address */ } else { perror("hostname_to_ip() failed"); return -1; } } /* create a socket */ if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1) { printf("socket created\n"); } /* bind it to all local addresses and pick any port number */ memset((char *)&myaddr, 0, sizeof(myaddr)); myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = htonl(INADDR_ANY); myaddr.sin_port = htons(0); if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { perror("bind failed"); return -1; } /* now define remaddr, the address to whom we want to send messages */ /* For convenience, the host address is expressed as a numeric IP address */ /* that we will convert to a binary format via inet_aton */ memset((char *) &remaddr, 0, sizeof(remaddr)); remaddr.sin_family = AF_INET; remaddr.sin_port = htons(port); if (inet_aton(host, &remaddr.sin_addr)==0) { fprintf(stderr, "inet_aton() failed\n"); exit(1); } /* set socket timeout */ struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) < 0) { perror("Error"); } /* now let's send the messages */ printf("Sending datagram '%s' to '%s' on port %d\n", msg, host, port); if (sendto(fd, msg, strlen(msg), 0, (struct sockaddr *)&remaddr, slen)==-1) { perror("sendto"); exit(1); } /* now receive an acknowledgment from the server */ recvlen = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&remaddr, &slen); if (recvlen >= 0) { buf[recvlen] = '\0'; /* expect a printable string - terminate it */ printf("response: \n%s\n", buf); } else { /* timeout */ printf("socket receive timeout\n"); } close(fd); return 0; /* ok */ }