#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <time.h> #include <sys/time.h> #include <errno.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <sys/types.h> #include <sys/select.h>
#define SERV_ADDR "127.0.0.1" #define SERV_PORT 5358 #define BUF_LEN 1024
#define MAX(a, b) (a)>(b)?(a):(b)
ssize_t writen(int fd, const void *vptr, size_t n) { size_t nleft; ssize_t nwriten; const char *ptr;
ptr = vptr; nleft = n; while(nleft>0) { if((nwriten = write(fd, ptr, nleft)) <= 0) { if(nwriten < 0 && errno == EINTR) { nwriten = 0; /*interrupt by signal*/ } else { return -1; } }
nleft -= nwriten; ptr += nwriten; } return n; }
char *gf_time() { struct timeval tv; static char str[30]; char *ptr;
if(gettimeofday(&tv, NULL) < 0) printf("gettimeofday error.\n");
ptr = ctime(&tv.tv_sec); strcpy(str, &ptr[11]); snprintf(str+8, sizeof(str)-8, ".%06ld", tv.tv_usec);
return str; }
void str_cli(FILE *fp, int sockfd) { int maxfdp1, val, stdineof; ssize_t n, nwritten; fd_set rset, wset; char to[BUF_LEN] = {0}, fr[BUF_LEN] = {0}; char *toiptr, *tooptr, *froptr, *friptr;
val = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, val | O_NONBLOCK);
val = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, val | O_NONBLOCK);
val = fcntl(STDOUT_FILENO, F_GETFL, 0); fcntl(STDOUT_FILENO, F_SETFL, val | O_NONBLOCK);
toiptr = tooptr = to; friptr = froptr = fr; stdineof = 0;
maxfdp1 = MAX(MAX(STDIN_FILENO, STDOUT_FILENO), sockfd) + 1;
while(1) { FD_ZERO(&rset); FD_ZERO(&wset); if(stdineof == 0 && toiptr < &to[BUF_LEN]) FD_SET(STDIN_FILENO, &rset); if(friptr < &fr[BUF_LEN]) FD_SET(sockfd, &rset); if(tooptr != toiptr) FD_SET(sockfd, &wset); if(froptr != friptr) FD_SET(STDOUT_FILENO, &wset); select(maxfdp1, &rset, &wset, NULL, NULL);
if(FD_ISSET(STDIN_FILENO, &rset)) { if((n = read(STDIN_FILENO, toiptr, &to[BUF_LEN] - toiptr)) < 0) { if(errno != EAGAIN) { printf("read error\n"); return; } } else if(n == 0) { fprintf(stderr, "%s: EOF on stdin\n", gf_time()); stdineof = 1; if(tooptr == toiptr) shutdown(sockfd, SHUT_WR); } else { fprintf(stderr, "%s: read %d bytes from stdin\n", gf_time(), n); toiptr += n; FD_SET(sockfd, &wset); } } if(FD_ISSET(sockfd, &rset)) { if((n = read(sockfd, friptr, &fr[BUF_LEN] - friptr)) < 0) { if(errno != EAGAIN) { printf("read error\n"); return; } } else if(n == 0) { fprintf(stderr, "%s: EOF on socket\n", gf_time()); if(stdineof) return; else { printf("strcli: server terminated prematurely!\n"); return; } } else { fprintf(stderr, "%s: read %d bytes from socket\n", gf_time(), n); friptr += n; FD_SET(STDOUT_FILENO, &wset); } } if(FD_ISSET(STDOUT_FILENO, &wset) && ((n = friptr - froptr) > 0)) { if((nwritten = write(STDOUT_FILENO, froptr, n)) < 0) { if(errno != EWOULDBLOCK) printf("write error to stdout.\n"); } else { fprintf(stderr, "%s: wrote %d bytes to stdout\n", gf_time(), nwritten); froptr += nwritten; if(froptr == friptr) froptr = friptr = fr; } } if(FD_ISSET(sockfd, &wset) && ((n = toiptr - tooptr) > 0 )) { if((nwritten = write(sockfd, tooptr, n)) < 0) { if(errno != EWOULDBLOCK) printf("write error to socket.\n"); } else { fprintf(stderr, "%s: wrote %d bytes to socket\n", gf_time(), nwritten); tooptr += nwritten; if(tooptr == toiptr) { tooptr = toiptr = to; if(stdineof) shutdown(sockfd, SHUT_WR); } } } } return; }
int main(int argc, char **argv) { int fd; struct sockaddr_in servaddr;
fd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(SERV_ADDR); servaddr.sin_port = htons(SERV_PORT);
if (connect(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) { printf("connect error: %s\n", strerror(errno)); return 0; }
str_cli(stdin, fd); return 0; }
|