diff options
Diffstat (limited to 'pgm4/inet_dgrams.d')
-rw-r--r-- | pgm4/inet_dgrams.d/Makefile | 17 | ||||
-rw-r--r-- | pgm4/inet_dgrams.d/README | 11 | ||||
-rw-r--r-- | pgm4/inet_dgrams.d/fancy_recv_udp.c | 117 | ||||
-rw-r--r-- | pgm4/inet_dgrams.d/recv_udp.c | 115 | ||||
-rw-r--r-- | pgm4/inet_dgrams.d/send_udp.c | 87 |
5 files changed, 347 insertions, 0 deletions
diff --git a/pgm4/inet_dgrams.d/Makefile b/pgm4/inet_dgrams.d/Makefile new file mode 100644 index 0000000..14018f2 --- /dev/null +++ b/pgm4/inet_dgrams.d/Makefile @@ -0,0 +1,17 @@ +CC=gcc +CFLAGS=-g -Wall + +all: recv_udp send_udp fancy_recv_udp + +recv_udp: recv_udp.o + $(CC) -o recv_udp recv_udp.o + +fancy_recv_udp: fancy_recv_udp.o + $(CC) -o fancy_recv_udp fancy_recv_udp.o + +send_udp: send_udp.o + $(CC) -o send_udp send_udp.o + +clean: + rm -f *.o recv_udp send_udp fancy_recv_udp + diff --git a/pgm4/inet_dgrams.d/README b/pgm4/inet_dgrams.d/README new file mode 100644 index 0000000..d5bac0f --- /dev/null +++ b/pgm4/inet_dgrams.d/README @@ -0,0 +1,11 @@ +Some simple programs which do datagram-based message passing on the +Internet. + +----------- + +send_udp.c and recv_udp.c are the simple send/receive processes. + +send_udp.c and fancy_recv_udp.c implement the "fancy" receiver that + was described in lecture. + + diff --git a/pgm4/inet_dgrams.d/fancy_recv_udp.c b/pgm4/inet_dgrams.d/fancy_recv_udp.c new file mode 100644 index 0000000..bb4c20a --- /dev/null +++ b/pgm4/inet_dgrams.d/fancy_recv_udp.c @@ -0,0 +1,117 @@ +/*********************************************************************\ +* FANCY_RECV_UDP.C * +* Test of UDP/IP. Receive datagrams on internet socket bound to port * +* 0x3333 on the local host. * +* * +* To use: * +* 1) On the appropriate host, invoke this code by * +* "fancy_recv_udp&". * +* 2) Invoke send_udp as many times as desired on the * +* remote host. * +* * +* Phil Kearns * +* April 11, 1987 * +* * +* Modified: April 10, 1992 * +* responds to input (CR) on stdin by cleanly shutting down * +* also shuts down if no datagrams for a minute * +\*********************************************************************/ + +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/inet.h> +#include <stdlib.h> + +void printsin(struct sockaddr_in*, char*, char*); + +int main() +{ + int socket_fd, cc, hits, ecode; + socklen_t fsize; + fd_set mask; + struct timeval timeout; + struct sockaddr_in *s_in, from; + struct addrinfo hints, *addrlist; + + struct { + char head; + u_long body; + char tail; + } msg; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE; hints.ai_protocol = 0; + hints.ai_canonname = NULL; hints.ai_addr = NULL; + hints.ai_next = NULL; + + ecode = getaddrinfo(NULL, "13107", &hints, &addrlist); + if (ecode != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ecode)); + exit(1); + } + + s_in = (struct sockaddr_in *) addrlist->ai_addr; + + printsin(s_in, "FANCY_RECV_UDP", "Local socket is:"); fflush(stdout); + + + socket_fd = socket (addrlist->ai_family, addrlist->ai_socktype, 0); + if (socket_fd < 0) { + perror ("fancy_recv_udp:socket"); + exit (1); + } + +/* + bind port 0x3333 on the current host to the socket accessed through + socket_fd. If port in use, die. +*/ + if (bind(socket_fd, (struct sockaddr *)s_in, sizeof(struct sockaddr_in)) < 0) { + perror("fancy_recv_udp:bind"); + exit(1); + } + + for(;;) { + fsize = sizeof(from); +/* Here's the new stuff. Hang a select on the file descriptors 0 (stdin) + and socket_fd looking to see if either descriptor is able to be read. + If it's stdin, shut down. If it's socket_fd, proceed as normal. If + Nothing happens for a minute, shut down also. +*/ + FD_ZERO(&mask); + FD_SET(0,&mask); + FD_SET(socket_fd,&mask); + timeout.tv_sec = 60; + timeout.tv_usec = 0; + if ((hits = select(socket_fd+1, &mask, (fd_set *)0, (fd_set *)0, + &timeout)) < 0) { + perror("fancy_recv_udp:select"); + exit(1); + } + if ( (hits==0) || ((hits>0) && (FD_ISSET(0,&mask))) ) { + printf("Shutting down\n"); + exit(0); + } + cc = recvfrom(socket_fd,&msg,sizeof(msg),0,(struct sockaddr *)&from,&fsize); + if (cc < 0) perror("recv_udp:recvfrom"); + printsin( &from, "recv_udp: ", "Packet from:"); + printf("Got data ::%c%u%c\n",msg.head,ntohl(msg.body),msg.tail); + fflush(stdout); + } + exit(0); +} + +void printsin(struct sockaddr_in *sin, char *m1, char *m2 ) +{ + char fromip[INET_ADDRSTRLEN]; + + printf ("%s %s:\n", m1, m2); + printf (" family %d, addr %s, port %d\n", sin -> sin_family, + inet_ntop(AF_INET, &(sin->sin_addr.s_addr), fromip, sizeof(fromip)), + ntohs((unsigned short)(sin -> sin_port))); +} diff --git a/pgm4/inet_dgrams.d/recv_udp.c b/pgm4/inet_dgrams.d/recv_udp.c new file mode 100644 index 0000000..24c47b5 --- /dev/null +++ b/pgm4/inet_dgrams.d/recv_udp.c @@ -0,0 +1,115 @@ +/*********************************************************************\ +* RECV_UDP.C * +* Test of UDP/IP. Receive datagrams on internet socket bound to port * +* 0x3333 on the local host. * +* * +* To use: * +* 1) On the appropriate host, invoke this code by * +* "recv_udp&". * +* 2) Invoke send_udp as many times as desired on the * +* remote host. * +* 3) When done, MAKE SURE TO KILL THIS BACKGROUND PROCESS! * +* * +* Phil Kearns * +* April 11, 1987 * +* * +* Modified February 2009: use getaddrinfo() * +\*********************************************************************/ + +#include <stdlib.h> +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/inet.h> + +void printsin(struct sockaddr_in*, char*, char*); + +int main() +{ + int socket_fd, cc, ecode; + socklen_t fsize; + struct sockaddr_in *s_in, from; + struct addrinfo hints, *addrlist; + void printsin(); + + struct { + char head; + u_long body; + char tail; + } msg; + +/* + In order to attach a name to the socket created above, first fill + in the appropriate blanks in an inet socket address data structure + called "s_in". We blindly pick port number 0x3333. The second step + is to BIND the address to the socket. If port 0x3333 is in use, the + bind system call will fail detectably. +*/ + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE; hints.ai_protocol = 0; + hints.ai_canonname = NULL; hints.ai_addr = NULL; + hints.ai_next = NULL; + +/* + getaddrinfo() should return a single result, denoting + a SOCK_DGRAM socket on any interface of this system at + port 0x3333. +*/ + + ecode = getaddrinfo(NULL, "13107", &hints, &addrlist); + if (ecode != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ecode)); + exit(1); + } + + s_in = (struct sockaddr_in *) addrlist->ai_addr; + + printsin(s_in, "RECV_UDP", "Local socket is:"); fflush(stdout); + +/* + Create the socket to be used for datagram reception. Initially, + it has no name in the internet (or any other) domain. +*/ + socket_fd = socket (addrlist->ai_family, addrlist->ai_socktype, 0); + if (socket_fd < 0) { + perror ("recv_udp:socket"); + exit (1); + } + +/* + bind port 0x3333 on the current host to the socket accessed through + socket_fd. If port in use, bind() will fail and we die. +*/ + + if (bind(socket_fd, (struct sockaddr *)s_in, sizeof(struct sockaddr_in)) < 0) { + perror("recv_udp:bind"); + exit(1); + } + + for(;;) { + fsize = sizeof(from); + cc = recvfrom(socket_fd, &msg, sizeof(msg), 0, (struct sockaddr *)&from, &fsize); + if (cc < 0) perror("recv_udp:recvfrom"); + printsin( &from, "recv_udp: ", "Packet from:"); + printf("Got data ::%c%u%c\n",msg.head,ntohl(msg.body),msg.tail); + fflush(stdout); + } + exit(0); +} + +void printsin(struct sockaddr_in *sin, char *m1, char *m2 ) +{ + char fromip[INET_ADDRSTRLEN]; + + printf ("%s %s:\n", m1, m2); + printf (" family %d, addr %s, port %d\n", sin -> sin_family, + inet_ntop(AF_INET, &(sin->sin_addr.s_addr), fromip, sizeof(fromip)), + ntohs((unsigned short)(sin -> sin_port))); +} diff --git a/pgm4/inet_dgrams.d/send_udp.c b/pgm4/inet_dgrams.d/send_udp.c new file mode 100644 index 0000000..63a3c96 --- /dev/null +++ b/pgm4/inet_dgrams.d/send_udp.c @@ -0,0 +1,87 @@ +/***********************************************************************\ +* SEND_UDP.C * +* Test of UDP/IP. Send a single dippy datagram to a receiver process * +* assumed to exist on port 0x3333 on the internet host specified as * +* the single argument to this program. * +* * +* To use: * +* 1) Make sure that recv_udp is running (probably in the * +* background on the target host. * +* 2) Issue the command "send_udp xx", where xx is a host name. * +* * +* Phil Kearns * +* April 11, 1987 * +* * +* Modified February 2009: use getaddrinfo() * +\***********************************************************************/ + +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> + +int main(int argc,char **argv) +{ + int socket_fd, cc, ecode; + struct sockaddr_in *dest; + struct addrinfo hints, *addrlist; + struct { + char head; + u_long body; + char tail; + } msgbuf; + + +/* + Use getaddrinfo to create a SOCK_DGRAM sockarddr_in set + up for the host specified as argv[1] and port 0x3333. +*/ + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_NUMERICSERV; hints.ai_protocol = 0; + hints.ai_canonname = NULL; hints.ai_addr = NULL; + hints.ai_next = NULL; + + ecode = getaddrinfo(argv[1], "13107", &hints, &addrlist); + if (ecode != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ecode)); + exit(1); + } + + dest = (struct sockaddr_in *) addrlist->ai_addr; // Will use in sendto(). + +/* + Set up a datagram (UDP/IP) socket in the Internet domain. + We will use it as the handle thru which we will send a + single datagram. Note that, since this no message is ever + addressed TO this socket, we do not bind an internet address + to it. It will be assigned a (temporary) address when we send + a message thru it. +*/ + + socket_fd = socket (addrlist->ai_family, addrlist->ai_socktype, 0); + if (socket_fd == -1) { + perror ("send_udp:socket"); + exit (1); + } + + msgbuf.head = '<'; + msgbuf.body = htonl(getpid()); + msgbuf.tail = '>'; + + cc = sendto(socket_fd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr *) dest, + sizeof(struct sockaddr_in)); + if (cc < 0) { + perror("send_udp:sendto"); + exit(1); + } + + exit(0); +} |