earth% 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 -lsocket -lnsl 13 Command syntax: forward_cli server_name (either DNS or IP) 14 Sam Hsu (10/7/03) 15 */ 16 #include 17 #include 18 #include 19 #include 20 #include 21 #include 22 #include 23 #include 24 #include 25 #define max(a1, a2) (a1 >= a2 ? a1 : a2) 26 #define SER_PORT 49499 27 main(int argc, char *argv[]) 28 { 29 int cli_sock, ser_len, port_number; 30 int res, rfd, maxfdp1; 31 size_t nread; 32 fd_set readset; 33 char buf[BUFSIZ], filename[BUFSIZ]; 34 struct sockaddr_in ser; 35 struct hostent *ser_info; 36 struct timeval timeout; 37 fd_set saverset; 38 /* to open a socket */ 39 if ((cli_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 40 fprintf(stderr, "Unable to create socket for client\n"); 41 exit(1); 42 } 43 /* to initialize server sockaddr_in structure */ 44 ser_len = sizeof(ser); /* to get ser length */ 45 bzero((char *)&ser, ser_len); /* to zero out struct */ 46 ser.sin_family = AF_INET; /* Internet domain */ 47 ser.sin_port = htons(SER_PORT); /* echo server port number */ 48 if ((ser_info = gethostbyname(argv[1])) == (struct hostent *)NULL) { 49 fprintf(stderr, "unknown server\n"); 50 exit(2); 51 } 52 bcopy((char *)ser_info->h_addr, (char *)&ser.sin_addr, ser_info->h_length); 53 /* to get filename, open it, and send filename to server */ 54 nread = read(STDIN_FILENO, buf, BUFSIZ); /* get filename from stdin */ 55 strncpy(filename, buf, nread); 56 filename[nread-1] = '\0'; /* remove '\n' & end with '\0' */ 57 if ((rfd = open(filename, O_RDONLY)) == -1) { 58 fprintf(stderr, "Can't open file\n"); 59 exit(3); 60 } 61 sendto(cli_sock, buf, nread, 0, (struct sockaddr *)&ser, ser_len); 62 nread = recvfrom(cli_sock, buf, BUFSIZ, 0, 63 (struct sockaddr *)&ser, &ser_len); 64 write(STDOUT_FILENO, buf, nread); /* write out to screen */ 65 /* to get ready for test for read using select() */ 66 FD_ZERO(&readset); /* clear all bits in readset */ 67 FD_SET(rfd, &readset); /* turn on bit for rfd in readset */ 68 FD_SET(cli_sock, &readset); /* turn on bit for cli_sock */ 69 maxfdp1 = max(rfd, cli_sock) + 1; /* get the max number of fd's */ 70 timeout.tv_sec = 60; /* max wait 60 sec */ 71 timeout.tv_usec = 0; 72 /* to start read/send using select() */ 73 saverset = readset; 74 while (1) { 75 if (res = select(maxfdp1, &readset, NULL, NULL, &timeout)) { 76 if (res == -1) { 77 perror("select() failed"); 78 break; /* error */ 79 } 80 if (FD_ISSET(cli_sock, &readset)) { /* socket is readable */ 81 nread = recvfrom(cli_sock, buf, BUFSIZ, 0, 82 (struct sockaddr *)&ser, &ser_len); 83 write(STDOUT_FILENO, buf, nread); /* write out to screen */ 84 } 85 if (FD_ISSET(rfd, &readset)) { /* more data in file */ 86 nread = read(rfd, buf, BUFSIZ); /* get data from file */ 87 if (nread == 0) { /* EOF */ 88 close(rfd); /* must close */ 89 FD_CLR(rfd, &saverset); /* remove it from read */ 90 } else 91 sendto(cli_sock, buf, nread, 0, /* send to server */ 92 (struct sockaddr *)&ser, ser_len); 93 } 94 } else 95 break; /* exit infinite loop on tiemout */ 96 readset = saverset; /* to reset it */ 97 } 98 close(cli_sock); 99 } /* main */ earth% 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 = 49499, 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 -lsocket 13 Command syntax: forward_ser & 14 Sam Hsu (10/7/03) 15 */ 16 #include 17 #include 18 #include 19 #include 20 #include 21 #define MAXCLI 2 /* max # of concurrent clients */ 22 #define SER_PORT 49499 /* 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 */ reality% forward_ser & [1] 6795 earth% forward_cli reality.cse.fau.edu file1 file2 ... # displays contents of file2 # wait for time out polaris% forward_cli 131.91.96.105 file2 file1 ... # displays contents of file1 # wait for time out reality% 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 main() 7 { 8 int i, val, nread; 9 char buf[BUFSIZ]; 10 char mesg[] = "\tNo keyboard input\n", 11 mesg1[] = "Waiting for input >> "; 12 val = fcntl(0, F_GETFL, 0); /* get current file status flags */ 13 val |= O_NONBLOCK; /* turn off blocking flag */ 14 fcntl(0, F_SETFL, val); /* set up non-blocking read */ 15 for (i = 0; i < 10; i++) { /* to loop around 10 (arbitrary) times */ 16 nread = read(0, buf, BUFSIZ); 17 if (nread > 0) 18 write(1, buf, nread); 19 else 20 write(1, mesg, strlen(mesg)); 21 sleep(2); /* to get some delay */ 22 } 23 val &= ~O_NONBLOCK; /* turn on blocking flag */ 24 fcntl(0, F_SETFL, val); /* go back to blocking read */ 25 write(1, mesg1, strlen(mesg1)); 26 nread = read(0, buf, BUFSIZ); 27 write(1, buf, nread); 28 } 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