/* Operating Systems Spring 2005 Sample UDP socket code This program can run in one of two modes: 1. as a server that creates a UDP socket and waits for datagrams. For every datagram received, the server sends the message to STDOUT. To stop the server you need to use ^C To run this program as a server: > ./udpplay -s portnum 2. as a client. The client uses the server specified on the command line (as hostname:port). The client reads a line at a time from stdin (using readline), and sends each line to the server as a UDP datagram. The client will quit if it sees EOF from stdin, or if it reads the string "quit". To run this program as a client: > ./udpplay -c server:port */ #include #include #include #include #include /* socket specific definitions */ #include /* INET constants and stuff */ #include /* IP address conversion stuff */ #include /* gethostbyname */ #include #include /* when acting as the server, this function is called. udp_server waits for datagrams, and sends each to stdout. */ void udp_server(int port) { int sd; int addrlen; char dgrambuf[1000]; /* largest datagram we can handle is 1000 chars! */ int len; struct sockaddr_in from; struct sockaddr_in skaddr; /* create a socket IP protocol family (PF_INET) UDP protocol (SOCK_DGRAM) */ if ((sd = socket( PF_INET, SOCK_DGRAM, 0 )) < 0) { perror("Problem creating socket\n"); exit(1); } /* establish our address address family is AF_INET our IP address is INADDR_ANY (any of our IP addresses) the port must be in network byte order! */ skaddr.sin_family = AF_INET; skaddr.sin_addr.s_addr = htonl(INADDR_ANY); skaddr.sin_port = htons(port); if (bind(sd, (struct sockaddr *) &skaddr, sizeof(skaddr))<0) { perror("Problem binding\n"); exit(1); } printf("waiting for messages...\n"); while (1) { addrlen=sizeof(from); if ((len = recvfrom(sd,dgrambuf,1000,0, (struct sockaddr*)&from,&addrlen))<0) { perror("Problem calling recvfrom"); exit(1); } write(STDOUT_FILENO,"received: ",10); write(STDOUT_FILENO,dgrambuf,len); write(STDOUT_FILENO,"\n",1); } } /* ====================================================== udp_client is called if this is run as a client. The client creates a datagram socket, and a sockaddr with the server's address. Then the client reads from stdin (using readline), and unless the line is "quit", sends each line to the server. Also quits if stdin is closed... */ void udp_client(char *server_hostname,int port) { int sd; char *line; struct sockaddr_in skaddr; struct hostent *hp; /* create a udp socket */ if ((sd = socket( PF_INET, SOCK_DGRAM, 0 )) < 0) { perror("Problem creating socket"); exit(1); } /* fill in an address structure that will be used to specify the address of the server we want to connect to address family is IP (AF_INET) server IP address is found by calling gethostbyname with the name of the server */ skaddr.sin_family = AF_INET; /* convert hostname to a network byte order binary IP address */ /* First try to convert using gethostbyname */ if ((hp = gethostbyname(server_hostname))!=0) { /* Name lookup was successful - copy the IP address */ memcpy( &skaddr.sin_addr.s_addr, hp->h_addr, hp->h_length); } else { /* Name lookup didn't work, try converting from dotted decimal */ if (inet_aton(server_hostname,&skaddr.sin_addr)==0) { printf("Invalid IP address: %s\n",server_hostname); exit(1); } } /* port must be in network byte order! */ skaddr.sin_port = htons(port); while (line = readline("What should I send? ")) { if (sendto(sd,line,strlen(line),0, (struct sockaddr *)&skaddr,sizeof(skaddr))<0) { perror("Error calling sendto "); exit(1); } free(line); } } enum {NONE=0,CLIENT, SERVER}; int main(int argc, char **argv) { int mode = NONE; char *server=NULL; int i; int port=0; char c; while ((c=getopt(argc,argv,"c:s:"))>=0) { switch(c) { case 'c': mode = CLIENT; /* parse the string to get the server name and port */ server = (char *) malloc(strlen(optarg)); i=0; while (*optarg && *optarg!=':') { server[i++]=*optarg; optarg++; } server[i]=0; if (*optarg != ':') { printf("Invalid server address, should be server:port\n"); exit(1); } port = atoi(optarg+1); break; case 's': mode = SERVER; port = atoi(optarg); break; case '?': /* invalid option - getopt returns a '?' */ exit(1); } } if ((mode==NONE) || (port<=0)) { printf("Invalid command line. Usage: %s (-s port | -c server:port)\n",argv[0]); exit(0); } if (mode==SERVER) { udp_server(port); } else { udp_client(server,port); } return(1); }