pluto% num forward_cli.c 1 /* forward_cli.c 2 This the client program for forward_ser.c 3 Algorithm outline: 4 a. Open a UDP socket. 5 b. Initialize server socket address structure 6 c. Get filename from user, open it for read, and send filename to server 7 d. Wait for server to send filename from another client 8 e. Get ready to use select() 9 f. Use select() to see which fd is ready for read/write 10 g. go back to f until no more fd is ready, or timeout 11 h. Close socket. 12 To compile: gcc -o forward_cli forward_cli.c 13 Command syntax: forward_cli server_name (either DNS or IP) 14 Sam Hsu (10/26/10) 15 */ 16 #include 17 #include 18 #include 19 #include 20 #include 21 #include 22 #include 23 #include 24 #define max(a1, a2) (a1 >= a2 ? a1 : a2) 25 #define SER_PORT 51015 /* an arbitrary number > 49151 */ 26 main(int argc, char *argv[]) 27 { 28 int cli_sock, ser_len, port_number; 29 int res, rfd, maxfdp1; 30 size_t nread; 31 fd_set readset; 32 char buf[BUFSIZ], filename[BUFSIZ]; 33 struct sockaddr_in ser; 34 struct hostent *ser_info; 35 struct timeval timeout; 36 fd_set saverset; 37 /* to open a socket */ 38 if ((cli_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 39 fprintf(stderr, "Unable to create socket for client\n"); 40 exit(1); 41 } 42 /* to initialize server sockaddr_in structure */ 43 ser_len = sizeof(ser); /* to get ser length */ 44 bzero((char *)&ser, ser_len); /* to zero out struct */ 45 ser.sin_family = AF_INET; /* Internet domain */ 46 ser.sin_port = htons(SER_PORT); /* echo server port number */ 47 if ((ser_info = gethostbyname(argv[1])) == (struct hostent *)NULL) { 48 fprintf(stderr, "unknown server\n"); 49 exit(2); 50 } 51 bcopy((char *)ser_info->h_addr, (char *)&ser.sin_addr, ser_info->h_length); 52 /* to get filename, open it, and send filename to server */ 53 nread = read(STDIN_FILENO, buf, BUFSIZ); /* get filename from stdin */ 54 strncpy(filename, buf, nread); 55 filename[nread-1] = '\0'; /* remove '\n' & end with '\0' */ 56 if ((rfd = open(filename, O_RDONLY)) == -1) { 57 fprintf(stderr, "Can't open file\n"); 58 exit(3); 59 } 60 sendto(cli_sock, buf, nread, 0, (struct sockaddr *)&ser, ser_len); 61 nread = recvfrom(cli_sock, buf, BUFSIZ, 0, 62 (struct sockaddr *)&ser, &ser_len); 63 write(STDOUT_FILENO, buf, nread); /* write out to screen */ 64 /* to get ready for test for read using select() */ 65 FD_ZERO(&readset); /* clear all bits in readset */ 66 FD_SET(rfd, &readset); /* turn on bit for rfd in readset */ 67 FD_SET(cli_sock, &readset); /* turn on bit for cli_sock */ 68 maxfdp1 = max(rfd, cli_sock) + 1; /* get the max number of fd's */ 69 timeout.tv_sec = 60; /* max wait 60 sec */ 70 timeout.tv_usec = 0; 71 /* to start read/send using select() */ 72 saverset = readset; 73 while (1) { 74 if (res = select(maxfdp1, &readset, NULL, NULL, &timeout)) { 75 if (res == -1) { 76 perror("select() failed"); 77 break; /* error */ 78 } 79 if (FD_ISSET(cli_sock, &readset)) { /* socket is readable */ 80 nread = recvfrom(cli_sock, buf, BUFSIZ, 0, 81 (struct sockaddr *)&ser, &ser_len); 82 write(STDOUT_FILENO, buf, nread); /* write out to screen */ 83 } 84 if (FD_ISSET(rfd, &readset)) { /* more data in file */ 85 nread = read(rfd, buf, BUFSIZ); /* get data from file */ 86 if (nread == 0) { /* EOF */ 87 close(rfd); /* must close */ 88 FD_CLR(rfd, &saverset); /* remove it from read */ 89 } else 90 sendto(cli_sock, buf, nread, 0, /* send to server */ 91 (struct sockaddr *)&ser, ser_len); 92 } 93 } else 94 break; /* exit infinite loop on tiemout */ 95 readset = saverset; /* to reset it */ 96 } 97 close(cli_sock); 98 } /* main */ pluto% num forward_ser.c 1 /* forward_ser.c 2 This is a simple server that forwards datagrams between two clients. 3 Algorithm outline 4 a. Open a UDP socket 5 b. Initialize server socket address structure 6 c. Bind SER_PORT and INADDR_ANY to the open socket 7 (SER_PORT = 51015, an arbitrary number > 49151) 8 d. Wait for a datagram from each of the two clients to set up a 9 logical connection. 10 e. Read a datagram from one client and send it to the other client 11 f. go back to e. 12 To compile: gcc -o forward_ser forward_ser.c 13 Command syntax: forward_ser & 14 Sam Hsu (10/26/10) 15 */ 16 #include 17 #include 18 #include 19 #include 20 #include 21 #define MAXCLI 2 /* max # of concurrent clients */ 22 #define SER_PORT 51015 /* an arbitrary number > 49151 */ 23 main() 24 { 25 int i, clino, ser_sock, ser_len, cli_len, maxfdp1; 26 ssize_t nread; 27 char tempbuf[BUFSIZ], buf[MAXCLI][BUFSIZ]; 28 struct sockaddr_in ser, tempaddr, cli[MAXCLI]; 29 fd_set readset; 30 int bclients(struct sockaddr_in, struct sockaddr_in *), 31 clientno(struct sockaddr_in, struct sockaddr_in *); 32 /* to open a socket */ 33 if ((ser_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 34 fprintf(stderr, "Unable to create server socket\n"); 35 exit(1); 36 } 37 /* to initialize server sockaddr_in structure */ 38 ser_len = sizeof(ser); /* to get ser socket struct length */ 39 bzero((char *)&ser, ser_len); /* to zero out struct */ 40 ser.sin_family = AF_INET; /* domain Internet */ 41 ser.sin_port = htons(SER_PORT); 42 ser.sin_addr.s_addr = htonl(INADDR_ANY); /* any network interface */ 43 /* to bind open socket to an IPaddr/service port pair */ 44 if ((bind(ser_sock, (struct sockaddr *)&ser, ser_len)) == -1) { 45 fprintf(stderr, "Unable to bind to service port for server\n"); 46 exit(2); 47 } 48 /* to initialize sockaddr_in structures in the clients array */ 49 for (i = 0; i < MAXCLI; i++) 50 cli[i].sin_addr.s_addr = 0; 51 /* to wait for the first datagram from each client */ 52 cli_len = sizeof(tempaddr); 53 while (1) { 54 nread = recvfrom(ser_sock, tempbuf, BUFSIZ, 0, /* wait for a client */ 55 (struct sockaddr *)&tempaddr, &cli_len); 56 if (nread == (ssize_t)-1) { 57 fprintf(stderr, "recvfrom() failed\n"); 58 exit(3); 59 } 60 clino = bclients(tempaddr, cli); 61 strncpy(buf[clientno(tempaddr, cli)], tempbuf, (size_t)nread);/*memcpy BUG*/ 62 if (clino == MAXCLI) 63 break; 64 } 65 /* to forward initial datagrams between clients */ 66 for (i = 0; i < MAXCLI; i++) { 67 sendto(ser_sock, buf[i], strlen(buf[i]), 0, /* send to another client */ 68 (struct sockaddr *)&cli[(i+1)%2], cli_len); 69 } 70 /* to forward datagrams between clients - an infinite loop !! */ 71 while (1) { 72 for (i = 0; i < MAXCLI; i++) { 73 nread = recvfrom(ser_sock, tempbuf, BUFSIZ, MSG_PEEK, /* peek only */ 74 (struct sockaddr *)&tempaddr, &cli_len); 75 if (nread > 0) { 76 nread = recvfrom(ser_sock, tempbuf, BUFSIZ, 0, /* a real read */ 77 (struct sockaddr *)&tempaddr, &cli_len); 78 clino = clientno(tempaddr, cli); /* which client? */ 79 sendto(ser_sock, tempbuf, (size_t)nread, 0, /* forwarding */ 80 (struct sockaddr *)&cli[(clino+1)%2], cli_len); 81 } 82 } 83 } 84 close(ser_sock); /* close server socket */ 85 return(0); /* currently not reachable */ 86 } /* main */ 87 /* 88 bclients() is used to build an array of clients based on their IP addrs 89 */ 90 int bclients(struct sockaddr_in cli, struct sockaddr_in *cliary) 91 { 92 int i; 93 for (i = 0; i < MAXCLI; i++) { 94 if (cliary[i].sin_addr.s_addr != 0) { 95 if (cli.sin_addr.s_addr == cliary[i].sin_addr.s_addr) 96 continue; /* skip */ 97 } else { 98 cliary[i] = cli; /* copy cli infor over */ 99 return(i+1); /* return no of clients */ 100 } 101 } 102 return(i); /* return no of clients */ 103 } /* bclients */ 104 /* 105 clientno() is used to return the client number for a given IP addr 106 */ 107 int clientno(struct sockaddr_in cli, struct sockaddr_in *cliary) 108 { 109 int i; 110 for (i = 0; i < MAXCLI; i++) { 111 if (cli.sin_addr.s_addr == cliary[i].sin_addr.s_addr) 112 break; 113 } 114 return(i); 115 } /* clientno */ pluto% forward_ser & [1] 32143 lamp% forward_cli pluto.cse.fau.edu file1 file2 ... # displays contents of file2 # wait for time out polaris% forward_cli 131.91.97.19 file2 file1 ... # displays contents of file1 # wait for time out pluto% kill %1 [1] Killed forward_ser pluto% num read_nb.c 1 /* read_nb.c 2 This program illustrates how to do non-blocking reads. 3 */ 4 #include 5 #include 6 #include 7 main() 8 { 9 int i, val; 10 ssize_t nread; 11 char buf[BUFSIZ]; 12 char mesg[] = "\tNo keyboard input\n", 13 mesg1[] = "Waiting for input >> "; 14 val = fcntl(0, F_GETFL, 0); /* get current file status flags */ 15 val |= O_NONBLOCK; /* turn off blocking flag */ 16 fcntl(0, F_SETFL, val); /* set up non-blocking read */ 17 for (i = 0; i < 10; i++) { /* to loop around 10 (arbitrary) times */ 18 nread = read(0, buf, BUFSIZ); 19 if (nread > 0) 20 write(1, buf, nread); 21 else 22 write(1, mesg, strlen(mesg)); 23 sleep(2); /* to get some delay */ 24 } 25 val &= ~O_NONBLOCK; /* turn on blocking flag */ 26 fcntl(0, F_SETFL, val); /* go back to blocking read */ 27 write(1, mesg1, strlen(mesg1)); 28 nread = read(0, buf, BUFSIZ); 29 write(1, buf, nread); 30 } pluto% read_nb No keyboard input No keyboard input echo t echo t th No keyboard input is No keyboard input this 1 No keyboard input 34 134 No keyboard input No keyboard input Waiting for input >> end of input end of input