一、服务端程序
#include <stdio.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <sys/un.h> #include <sys/socket.h> #include <sys/wait.h> #define SA struct sockaddr #define UNIXSTR_PATH "/tmp/unix.str" #define LISTENQ 1024 #define MAXLINE 4096 typedef void Sigfunc(int); Sigfunc *signal(int, Sigfunc *); void err_sys(const char *, ...); void str_echo(int); ssize_t writen(int, const void *, size_t); int main(int argc, char **argv) { int listenfd, connfd; pid_t childpid; socklen_t clilen; struct sockaddr_un cliaddr, servaddr; void sig_chld(int); listenfd = socket(AF_LOCAL, SOCK_STREAM, 0); unlink(UNIXSTR_PATH); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, UNIXSTR_PATH); bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); listen(listenfd, LISTENQ); signal(SIGCHLD, sig_chld); for ( ; ; ) { clilen = sizeof(cliaddr); if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) { if (errno == EINTR) { continue; /* back to for() */ } else { err_sys("accept error"); } } if ( (childpid = fork()) == 0) { /* child process */ close(listenfd); /* close listening socket */ str_echo(connfd); /* process request */ exit(0); } close(connfd); /* parent closes connected socket */ } } Sigfunc *signal(int signo, Sigfunc *func) { struct sigaction act, oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (signo != SIGALRM) { act.sa_flags |= SA_RESTART; } if (sigaction(signo, &act, &oact) < 0) { return SIG_ERR; } return (oact.sa_handler); } void sig_chld(int signo) { pid_t pid; int stat; while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0) { printf("child %d terminated\n", pid); } return; } void str_echo(int sockfd) { ssize_t n; char buf[MAXLINE]; again: while ( (n = read(sockfd, buf, MAXLINE)) > 0) { writen(sockfd, buf, n); bzero(buf, sizeof(buf)); } if (n < 0 && errno == EINTR) { goto again; } else if (n < 0) { perror("read"); } } 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) { nwriten = 0; /* call write() again */ } else { return (-1); /* error */ } } nleft -= nwriten; ptr += nwriten; } return (n - nwriten); }
#include <stdio.h> #include <errno.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> /* ANSI C header file */ #include <syslog.h> /* for syslog() */ #define MAXLINE 4096 int daemon_proc; /* set nonzero by daemon_init() */ static void err_doit(int, int, const char *, va_list); /* Nonfatal error related to system call * Print message and return */ void err_ret(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_INFO, fmt, ap); va_end(ap); return; } /* Fatal error related to system call * Print message and terminate */ void err_sys(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_ERR, fmt, ap); va_end(ap); exit(1); } /* Fatal error related to system call * Print message, dump core, and terminate */ void err_dump(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, LOG_ERR, fmt, ap); va_end(ap); abort(); /* dump core and terminate */ exit(1); /* shouldn't get here */ } /* Nonfatal error unrelated to system call * Print message and return */ void err_msg(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(0, LOG_INFO, fmt, ap); va_end(ap); return; } /* Fatal error unrelated to system call * Print message and terminate */ void err_quit(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(0, LOG_ERR, fmt, ap); va_end(ap); exit(1); } /* Print message and return to caller * Caller specifies "errnoflag" and "level" */ static void err_doit(int errnoflag, int level, const char *fmt, va_list ap) { int errno_save, n; char buf[MAXLINE + 1]; errno_save = errno; /* value caller might want printed */ #ifdef HAVE_VSNPRINTF vsnprintf(buf, MAXLINE, fmt, ap); /* safe */ #else vsprintf(buf, fmt, ap); /* not safe */ #endif n = strlen(buf); if (errnoflag) snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save)); strcat(buf, "\n"); if (daemon_proc) { syslog(level, buf, NULL); } else { fflush(stdout); /* in case stdout and stderr are the same */ fputs(buf, stderr); fflush(stderr); } return; }
二、客户端程序
#include <stdio.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <sys/un.h> #define SA struct sockaddr #define UNIXSTR_PATH "/tmp/unix.str" #define MAXLINE 4096 void str_cli(FILE *, int); ssize_t writen(int, const void *, size_t); int main(int argc, char **argv) { int sockfd; struct sockaddr_un servaddr; socket: if ( (sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) { if (errno == EINTR) { goto socket; } else { perror("socket"); exit(-1); } } bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, UNIXSTR_PATH); connect: if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0) { if (errno == EINTR) { goto connect; } else { perror("connect"); exit(-1); } } str_cli(stdin, sockfd); /* do it all */ exit(0); } void str_cli(FILE *fp, int sockfd) { char sendline[MAXLINE], recvline[MAXLINE]; while(fgets(sendline, MAXLINE, fp) != NULL) { writen(sockfd, sendline, strlen(sendline)); if (read(sockfd, recvline, MAXLINE) < 0) { return; } fputs(recvline, stdout); bzero(recvline, sizeof(recvline)); } } ssize_t writen(int fd, const void *vptr, size_t n) { size_t nleft; ssize_t nwritten; const char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ( (nwritten = write(fd, ptr, nleft)) <= 0) { if (nwritten < 0 && errno == EINTR) { nwritten = 0; /* call write() again */ } else { return (-1); /* error */ } } nleft -= nwritten; ptr += nwritten; } return (n - nwritten); }