一、服务端程序
#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, );
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)) < ) {
if (errno == EINTR) {
continue; /* back to for() */
}
else {
err_sys("accept error");
}
}
if ( (childpid = fork()) == ) { /* child process */
close(listenfd); /* close listening socket */
str_echo(connfd); /* process request */
exit();
}
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 = ;
if (signo != SIGALRM) {
act.sa_flags |= SA_RESTART;
}
if (sigaction(signo, &act, &oact) < ) {
return SIG_ERR;
}
return (oact.sa_handler);
}
void sig_chld(int signo) {
pid_t pid;
int stat;
while ( (pid = waitpid(-, &stat, WNOHANG)) > ) {
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)) > ) {
writen(sockfd, buf, n);
bzero(buf, sizeof(buf));
}
if (n < && errno == EINTR) {
goto again;
} else if (n < ) {
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 > ) {
if ( (nwriten = write(fd, ptr, nleft)) <= ) {
if (nwriten < && errno) {
nwriten = ; /* call write() again */
} else {
return (-); /* 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(, 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(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
}
/* 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(, LOG_ERR, fmt, ap);
va_end(ap);
abort(); /* dump core and terminate */
exit(); /* 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(, 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(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
}
/* 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 + ];
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, )) < ) {
if (errno == EINTR) {
goto socket;
} else {
perror("socket");
exit(-);
}
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
strcpy(servaddr.sun_path, UNIXSTR_PATH);
connect:
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < ) {
if (errno == EINTR) {
goto connect;
} else {
perror("connect");
exit(-);
}
}
str_cli(stdin, sockfd); /* do it all */
exit();
}
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) < ) {
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 > ) {
if ( (nwritten = write(fd, ptr, nleft)) <= ) {
if (nwritten < && errno == EINTR) {
nwritten = ; /* call write() again */
} else {
return (-); /* error */
}
}
nleft -= nwritten;
ptr += nwritten;
}
return (n - nwritten);
}