1 #include "unp.h" 2 void 3 str_cli(FILE *fp, int sockfd) 4 { 5 int maxfdp1, val, stdineof; 6 ssize_t n, nwritten; 7 fd_set rset, wset; 8 char to[MAXLINE], fr[MAXLINE]; 9 char *toiptr, *tooptr, *friptr, *froptr;10 val = Fcntl(sockfd, F_GETFL, 0);11 Fcntl(sockfd, F_SETFL, val | O_NONBLOCK);12 val = Fcntl(STDIN_FILENO, F_GETFL, 0);13 Fcntl(STDIN_FILENO, F_SETFL, val | O_NONBLOCK);14 val = Fcntl(STDOUT_FILENO, F_GETFL, 0);15 Fcntl(STDOUT_FILENO, F_SETFL, val | O_NONBLOCK);16 toiptr = tooptr = to; /* initialize buffer pointers */17 friptr = froptr = fr;18 stdineof = 0;19 maxfdp1 = max(max(STDIN_FILENO, STDOUT_FILENO), sockfd) + 1;20 for ( ; ; ) {21 FD_ZERO(&rset);22 FD_ZERO(&wset);23 if (stdineof == 0 && toiptr < &to[MAXLINE])24 FD_SET(STDIN_FILENO, &rset); /* read from stdin */25 if (friptr < &fr[MAXLINE])26 FD_SET(sockfd, &rset); /* read from socket */27 if (tooptr != toiptr)28 FD_SET(sockfd, &wset); /* data to write to socket */29 if (froptr != friptr)30 FD_SET(STDOUT_FILENO, &wset); /* data to write to stdout */31 Select(maxfdp1, &rset, &wset, NULL, NULL);
32 if (FD_ISSET(STDIN_FILENO, &rset)) {33 if ( (n = read(STDIN_FILENO, toiptr, &to[MAXLINE] - toiptr)) < 0) {34 if (errno != EWOULDBLOCK)35 err_sys("read error on stdin");36 } else if (n == 0) {37 fprintf(stderr, "%s: EOF on stdin\n", gf_time());38 stdineof = 1; /* all done with stdin */39 if (tooptr == toiptr)40 Shutdown(sockfd, SHUT_WR); /* send FIN */41 } else {42 fprintf(stderr, "%s: read %d bytes from stdin\n", gf_time(),43 n);44 toiptr += n; /* # just read */45 FD_SET(sockfd, &wset); /* try and write to socket below */46 }47 }48 if (FD_ISSET(sockfd, &rset)) {49 if ( (n = read(sockfd, friptr, &fr[MAXLINE] - friptr)) < 0) {50 if (errno != EWOULDBLOCK)51 err_sys("read error on socket");52 } else if (n == 0) {53 fprintf(stderr, "%s: EOF on socket\n", gf_time());54 if (stdineof)55 return; /* normal termination */56 else57 err_quit("str_cli: server terminated prematurely");58 } else {59 fprintf(stderr, "%s: read %d bytes from socket\n",60 gf_time(), n);61 friptr += n; /* # just read */62 FD_SET(STDOUT_FILENO, &wset); /* try and write below */63 }64 }
65 if (FD_ISSET(STDOUT_FILENO, &wset) && ((n = friptr - froptr) > 0)) {66 if ( (nwritten = write(STDOUT_FILENO, froptr, n)) < 0) {67 if (errno != EWOULDBLOCK)68 err_sys("write error to stdout");69 } else {70 fprintf(stderr, "%s: wrote %d bytes to stdout\n",71 gf_time(), nwritten);72 froptr += nwritten; /* # just written */73 if (froptr == friptr)74 froptr = friptr = fr; /* back to beginning of buffer */75 }76 }77 if (FD_ISSET(sockfd, &wset) && ((n = toiptr - tooptr) > 0)) {78 if ( (nwritten = write(sockfd, tooptr, n)) < 0) {79 if (errno != EWOULDBLOCK)80 err_sys("write error to socket");81 } else {82 fprintf(stderr, "%s: wrote %d bytes to socket\n",83 gf_time(), nwritten);84 tooptr += nwritten; /* # just written */85 if (tooptr == toiptr) {86 toiptr = tooptr = to; /* back to beginning of buffer */87 if (stdineof)88 Shutdown(sockfd, SHUT_WR); /* send FIN */89 }90 }91 }92 }93 } 1 #include "unp.h" 2 #include <time.h> 3 char * 4 gf_time(void) 5 { 6 struct timeval tv; 7 static char str[30]; 8 char *ptr; 9 if (gettimeofday(&tv, NULL) < 0)10 err_sys("gettimeofday error");11 ptr = ctime(&tv.tv_sec);12 strcpy(str, &ptr[11]);13 /* Fri Sep 13 00:00:00 1986\n\0 */14 /* 0123456789012345678901234 5 */15 snprintf(str + 8, sizeof(str) - 8, ".%06ld", tv.tv_usec);16 return (str);17 }
这个例子中用到的两个 buffer 如下:1 #include "unp.h" 2 void 3 str_cli(FILE *fp, int sockfd) 4 { 5 pid_t pid; 6 char sendline[MAXLINE], recvline[MAXLINE]; 7 if ( (pid = Fork()) == 0) { /* child: server -> stdout */ 8 while (Readline(sockfd, recvline, MAXLINE) > 0) 9 Fputs(recvline, stdout); 10 kill(getppid(), SIGTERM); /* in case parent still running */ 11 exit(0); 12 } 13 /* parent: stdin -> server */ 14 while (Fgets(sendline, MAXLINE, fp) != NULL) 15 Writen(sockfd, sendline, strlen(sendline)); 16 Shutdown(sockfd, SHUT_WR); /* EOF on stdin, send FIN */ 17 pause(); 18 return; 19 }
1 #include "unp.h" 2 int 3 connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec) 4 { 5 int flags, n, error; 6 socklen_t len; 7 fd_set rset, wset; 8 struct timeval tval; 9 flags = Fcntl(sockfd, F_GETFL, 0); 10 Fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); 11 error = 0; 12 if ( (n = connect(sockfd, saptr, salen)) < 0) 13 if (errno != EINPROGRESS) 14 return (-1); 15 /* Do whatever we want while the connect is taking place. */ 16 if (n == 0) 17 goto done; /* connect completed immediately */ 18 FD_ZERO(&rset); 19 FD_SET(sockfd, &rset); 20 wset = rset; 21 tval.tv_sec = nsec; 22 tval.tv_usec = 0; 23 if ( (n = Select(sockfd + 1, &rset, &wset, NULL, 24 nsec ? &tval : NULL)) == 0) { 25 close(sockfd); /* timeout */ 26 errno = ETIMEDOUT; 27 return (-1); 28 } 29 if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) { 30 len = sizeof(error); 31 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) 32 return (-1); /* Solaris pending error */ 33 } else 34 err_quit("select error: sockfd not set"); 35 done: 36 Fcntl(sockfd, F_SETFL, flags); /* restore file status flags */ 37 if (error) { 38 close(sockfd); /* just in case */ 39 errno = error; 40 return (-1); 41 } 42 return (0); 43 }