《UNIX网络编程套接字联网API》这本书的示例中定义了许多包裹函数,它们的名称和标准函数一样,只是首字母变成大写字母;每个包裹函数完成实际的函数调用,检查返回值,并在发生错误时终止程序。
我在重写书上例子的时候,也仿照书上的方式,定义了许多包裹函数,提高程序的可读性(当然,我定义的包裹函数的错误处理没有书上例子这么详细了)
PS:这篇文章(博客)会持续更新。
文件my_unp.h:它定义了一些常量,声明了所有的包裹函数
- #ifndef MY_UNP_H_
- #define MY_UNP_H_
- #include <stdio.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <unistd.h>
- #include <errno.h>
- #include <pthread.h>
- #include <semaphore.h>
- #include <sys/socket.h>
- #include <sys/wait.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/select.h>
- #include <sys/epoll.h>
- #include <sys/poll.h>
- #include <sys/file.h>
- #include <sys/mman.h>
- #define MAXLINE 1024
- #define LISTENQ 1024
- #define MAXNITEMS 1000000
- #define MAXNTHREADS 100
- #define SERV_PORT 9877
- #define SERV_PORT_STR "9877"
- #define SA struct sockaddr
- typedef void Sigfunc(int);
- #define min(a,b) ((a) < (b) ? (a) : (b))
- #define max(a,b) ((a) > (b) ? (a) : (b))
- //错误处理函数,输出错误信息后退出程序
- void error_quit(char *fmt, ...);
- //为了适应网络的慢速IO而编写的读写函数
- ssize_t readn(int fd, void *vptr, size_t n);
- ssize_t writen(int fd, const void *vptr, size_t n);
- ssize_t readline(int fd, void *vptr, size_t maxlen);
- //各类读写包裹函数
- void Write(int fd, void *ptr, size_t nbytes);
- ssize_t Read(int fd, void *ptr, size_t nbytes);
- ssize_t Readn(int fd, void *ptr, size_t nbytes);
- void Writen(int fd, void *ptr, size_t nbytes);
- ssize_t Readline(int fd, void *ptr, size_t maxlen);
- void Fputs(const char *ptr, FILE *stream);
- char *Fgets(char *ptr, int n, FILE *stream);
- //各类标准包裹函数
- int Open(const char *pathname, int flags, mode_t mode);
- void Close(int fd);
- Sigfunc *Signal(int signo, Sigfunc *func);
- void *Malloc(size_t size);
- void *Calloc(size_t n, size_t size);
- void Pipe(int *fds);
- pid_t Fork(void);
- pid_t Waitpid(pid_t pid, int *iptr, int options);
- void Dup2(int fd1, int fd2);
- //各类网络包裹函数
- int Socket(int family, int type, int protocol);
- void Inet_pton(int family, const char *strptr, void *addrptr);
- void Connect(int fd, const struct sockaddr *sa, socklen_t salen);
- void Listen(int fd, int backlog);
- void Bind(int fd, const struct sockaddr *sa, socklen_t salen);
- int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
- const char *Inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
- int Select(int nfds, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout);
- int Poll(struct pollfd *fdarray, unsigned long nfds, int timeout);
- void Shutdown(int fd, int how);
- int Epoll_create(int size);
- void Epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
- int Epoll_wait(int epfd, struct epoll_event *events,
- int maxevents, int timeout);
- void Sendto(int fd, const void *ptr, size_t nbytes, int flags,
- const struct sockaddr *sa, socklen_t salen);
- ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags,
- struct sockaddr *sa, socklen_t *salenptr);
- void Setsockopt(int fd, int level, int optname,
- const void *optval, socklen_t optlen);
- void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
- void Munmap(void *addr, size_t len);
- void Ftruncate(int fd, off_t length);
- //各类和线程操作相关的包裹函数
- void Pthread_create(pthread_t *tid, const pthread_attr_t *attr,
- void * (*func)(void *), void *arg);
- void Pthread_detach(pthread_t tid);
- void Pthread_join(pthread_t tid, void **status);
- void Pthread_kill(pthread_t tid, int signo);
- void Pthread_mutex_lock(pthread_mutex_t *mptr);
- void Pthread_mutex_unlock(pthread_mutex_t *mptr);
- //此函数相当于UNP书上的set_concurrency函数
- void Pthread_setconcurrency(int level);
- void Pthread_cond_signal(pthread_cond_t *cptr);
- void Pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr);
- //各类和信号量相关的包裹函数
- sem_t *Sem_open(const char *name, int oflag,
- mode_t mode, unsigned int value);
- void Sem_close(sem_t *sem);
- void Sem_unlink(const char *pathname);
- void Sem_init(sem_t *sem, int pshared, unsigned int value);
- void Sem_destroy(sem_t *sem);
- void Sem_wait(sem_t *sem);
- void Sem_post(sem_t *sem);
- void Sem_getvalue(sem_t *sem, int *valp);
- #endif
文件unp_base.c:它定义了基本的包裹函数
- #include "my_unp.h"
- //此函数是在程序发生错误时被调用
- //先输出字符串fmt,再根据errno输出错误原因(如果有的话),最后退出程序
- //注:在多线程程序中,错误原因可能不正确
- void error_quit(char *fmt, ...)
- {
- int res;
- va_list list;
- va_start(list, fmt);
- res = vfprintf(stderr, fmt, list);
- if( errno != 0 )
- fprintf(stderr, " : %s", strerror(errno));
- fprintf(stderr, "\n", list);
- va_end(list);
- exit(1);
- }
- //字节流套接字上调用read时,输入的字节数可能比请求的数量少,
- //但这不是出错的状态,原因是内核中用于套接字的缓冲区可能已经达到了极限,
- //此时需要调用者再次调用read函数
- ssize_t readn(int fd, void *vptr, size_t n)
- {
- size_t nleft;
- ssize_t nread;
- char *ptr;
- ptr = vptr;
- nleft = n;
- while (nleft > 0)
- {
- if ( (nread = read(fd, ptr, nleft)) < 0)
- {
- if (errno == EINTR)
- nread = 0; /* and call read() again */
- else
- return(-1);
- }
- else if (nread == 0)
- break; /* EOF */
- nleft -= nread;
- ptr += nread;
- }
- return (n - nleft); /* return >= 0 */
- }
- //字节流套接字上调用write时,输出的字节数可能比请求的数量少,
- //但这不是出错的状态,原因是内核中用于套接字的缓冲区可能已经达到了极限,
- //此时需要调用者再次调用write函数
- 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; /* and call write() again */
- else
- return(-1); /* error */
- }
- nleft -= nwritten;
- ptr += nwritten;
- }
- return n;
- }
- static int read_cnt;
- static char *read_ptr;
- static char read_buf[MAXLINE];
- //内部函数my_read每次最多读MAXLINE个字节,然后每次返回一个字节
- static ssize_t my_read(int fd, char *ptr)
- {
- if (read_cnt <= 0)
- {
- again:
- if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0)
- {
- if (errno == EINTR)
- goto again;
- return(-1);
- }
- else if (read_cnt == 0)
- return(0);
- read_ptr = read_buf;
- }
- read_cnt--;
- *ptr = *read_ptr++;
- return 1;
- }
- //从描述符中读取文本行
- ssize_t readline(int fd, void *vptr, size_t maxlen)
- {
- ssize_t n, rc;
- char c, *ptr;
- ptr = vptr;
- for (n = 1; n < maxlen; n++)
- {
- if ( (rc = my_read(fd, &c)) == 1)
- {
- *ptr++ = c;
- if (c == '\n')
- break; /* newline is stored, like fgets() */
- }
- else if (rc == 0)
- {
- *ptr = 0;
- return(n - 1); /* EOF, n - 1 bytes were read */
- }
- else
- return(-1); /* error, errno set by read() */
- }
- *ptr = 0; /* null terminate like fgets() */
- return n;
- }
- ssize_t Readn(int fd, void *ptr, size_t nbytes)
- {
- ssize_t n = readn(fd, ptr, nbytes);
- if ( n < 0)
- error_quit("readn error");
- return n;
- }
- void Writen(int fd, void *ptr, size_t nbytes)
- {
- if ( writen(fd, ptr, nbytes) != nbytes )
- error_quit("writen error");
- }
- ssize_t Readline(int fd, void *ptr, size_t maxlen)
- {
- ssize_t n = readline(fd, ptr, maxlen);
- if ( n < 0)
- error_quit("readline error");
- return n;
- }
- ssize_t Read(int fd, void *ptr, size_t nbytes)
- {
- ssize_t n = read(fd, ptr, nbytes);
- if ( n == -1)
- error_quit("read error");
- return n;
- }
- void Write(int fd, void *ptr, size_t nbytes)
- {
- if (write(fd, ptr, nbytes) != nbytes)
- error_quit("write error");
- }
- int Open(const char *pathname, int flags, mode_t mode)
- {
- int fd = open(pathname, flags, mode);
- if( -1 == fd )
- error_quit("open file %s error", pathname);
- return fd;
- }
- void Close(int fd)
- {
- if (close(fd) == -1)
- error_quit("close error");
- }
- void Fputs(const char *ptr, FILE *stream)
- {
- if (fputs(ptr, stream) == EOF)
- error_quit("fputs error");
- }
- char *Fgets(char *ptr, int n, FILE *stream)
- {
- char *rptr = fgets(ptr, n, stream);
- if ( rptr == NULL && ferror(stream) )
- error_quit("fgets error");
- return rptr;
- }
- int Socket(int family, int type, int protocol)
- {
- int n = socket(family, type, protocol);
- if( n < 0)
- error_quit("socket error");
- return n;
- }
- void Inet_pton(int family, const char *strptr, void *addrptr)
- {
- int n = inet_pton(family, strptr, addrptr);
- if( n < 0)
- error_quit("inet_pton error for %s", strptr);
- }
- void Connect(int fd, const struct sockaddr *sa, socklen_t salen)
- {
- if (connect(fd, sa, salen) < 0)
- error_quit("connect error");
- }
- void Listen(int fd, int backlog)
- {
- if (listen(fd, backlog) < 0)
- error_quit("listen error");
- }
- void Bind(int fd, const struct sockaddr *sa, socklen_t salen)
- {
- if (bind(fd, sa, salen) < 0)
- error_quit("bind error");
- }
- int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
- {
- int n = accept(fd, sa, salenptr);
- if ( n < 0)
- error_quit("accept error");
- return n;
- }
- const char *Inet_ntop(int family, const void *addrptr, char *strptr, size_t len)
- {
- const char *ptr = inet_ntop(family, addrptr, strptr, len);
- if ( ptr == NULL)
- error_quit("inet_ntop error");
- return ptr;
- }
- pid_t Fork(void)
- {
- pid_t pid = fork();
- if ( pid == -1)
- error_quit("fork error");
- return pid;
- }
- Sigfunc *Signal(int signo, Sigfunc *func)
- {
- Sigfunc *sigfunc = signal(signo, func);
- if ( sigfunc == SIG_ERR)
- error_quit("signal error");
- return sigfunc;
- }
- int Select(int nfds, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout)
- {
- int n = select(nfds, readfds, writefds, exceptfds, timeout);
- if ( n < 0 )
- error_quit("select error");
- return n; /* can return 0 on timeout */
- }
- int Poll(struct pollfd *fdarray, unsigned long nfds, int timeout)
- {
- int n = poll(fdarray, nfds, timeout);
- if ( n < 0 )
- error_quit("poll error");
- return n;
- }
- void Shutdown(int fd, int how)
- {
- if (shutdown(fd, how) < 0)
- error_quit("shutdown error");
- }
- int Epoll_create(int size)
- {
- int n = epoll_create(size);
- if( n < 0 )
- error_quit("epoll create error");
- return n;
- }
- void Epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
- {
- if( epoll_ctl(epfd, op, fd, event) < 0 )
- error_quit("epoll ctl error");
- }
- int Epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
- {
- int n = epoll_wait(epfd, events, maxevents, timeout);
- if( n < 0 )
- error_quit("epoll wait error");
- return n;
- }
- void Sendto(int fd, const void *ptr, size_t nbytes, int flags,
- const struct sockaddr *sa, socklen_t salen)
- {
- if (sendto(fd, ptr, nbytes, flags, sa, salen) != (ssize_t)nbytes)
- error_quit("sendto error");
- }
- ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags,
- struct sockaddr *sa, socklen_t *salenptr)
- {
- ssize_t n = recvfrom(fd, ptr, nbytes, flags, sa, salenptr);
- if ( n < 0 )
- error_quit("recvfrom error");
- return n;
- }
- ssize_t Recvmsg(int fd, struct msghdr *msg, int flags)
- {
- ssize_t n = recvmsg(fd, msg, flags);
- if ( n < 0 )
- error_quit("recvmsg error");
- return(n);
- }
- void *Malloc(size_t size)
- {
- void *ptr = malloc(size);
- if ( ptr == NULL )
- error_quit("malloc error");
- return ptr;
- }
- void *Calloc(size_t n, size_t size)
- {
- void *ptr = calloc(n, size);
- if ( ptr == NULL)
- error_quit("calloc error");
- return ptr;
- }
- void Pipe(int *fds)
- {
- if ( pipe(fds) < 0 )
- error_quit("pipe error");
- }
- pid_t Waitpid(pid_t pid, int *iptr, int options)
- {
- pid_t retpid = waitpid(pid, iptr, options);
- if ( retpid == -1)
- error_quit("waitpid error");
- return retpid;
- }
- void Setsockopt(int fd, int level, int optname,
- const void *optval, socklen_t optlen)
- {
- if (setsockopt(fd, level, optname, optval, optlen) < 0)
- error_quit("setsockopt error");
- }
- void Socketpair(int family, int type, int protocol, int *fd)
- {
- int n = socketpair(family, type, protocol, fd);
- if ( n < 0 )
- error_quit("socketpair error");
- }
- void Dup2(int fd1, int fd2)
- {
- if (dup2(fd1, fd2) == -1)
- error_quit("dup2 error");
- }
- void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
- {
- void *ptr = mmap(addr, len, prot, flags, fd, offset);
- if ( ptr == MAP_FAILED )
- error_quit("mmap error");
- return ptr;
- }
- void Munmap(void *addr, size_t len)
- {
- if (munmap(addr, len) == -1)
- error_quit("munmap error");
- }
- void Ftruncate(int fd, off_t length)
- {
- if (ftruncate(fd, length) == -1)
- error_quit("ftruncate error");
- }
文件unp_pthread.c:它定义了基本的线程类包裹函数
- #include "my_unp.h"
- void Pthread_create(pthread_t *tid, const pthread_attr_t *attr,
- void * (*func)(void *), void *arg)
- {
- int n = pthread_create(tid, attr, func, arg);
- if ( n == 0)
- return;
- errno = n;
- error_quit("pthread_create error");
- }
- void Pthread_detach(pthread_t tid)
- {
- int n = pthread_detach(tid);
- if ( n == 0)
- return;
- errno = n;
- error_quit("pthread_detach error");
- }
- void Pthread_join(pthread_t tid, void **status)
- {
- int n = pthread_join(tid, status);
- if ( n == 0 )
- return;
- errno = n;
- error_quit("pthread_join error");
- }
- void Pthread_kill(pthread_t tid, int signo)
- {
- int n = pthread_kill(tid, signo);
- if ( n == 0 )
- return;
- errno = n;
- error_quit("pthread_kill error");
- }
- void Pthread_mutex_lock(pthread_mutex_t *mptr)
- {
- int n = pthread_mutex_lock(mptr);
- if ( n == 0 )
- return;
- errno = n;
- error_quit("pthread_mutex_lock error");
- }
- void Pthread_mutex_unlock(pthread_mutex_t *mptr)
- {
- int n = pthread_mutex_unlock(mptr);
- if ( n == 0 )
- return;
- errno = n;
- error_quit("pthread_mutex_unlock error");
- }
- void Pthread_setconcurrency(int level)
- {
- int n = pthread_setconcurrency(level);
- if ( n == 0 )
- return;
- errno = n;
- error_quit("pthread_mutex_unlock error");
- }
- void Pthread_cond_signal(pthread_cond_t *cptr)
- {
- int n = pthread_cond_signal(cptr);
- if ( n == 0 )
- return;
- errno = n;
- error_quit("pthread_cond_signal error");
- }
- void Pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr)
- {
- int n = pthread_cond_wait(cptr, mptr);
- if ( n == 0 )
- return;
- errno = n;
- error_quit("pthread_cond_wait error");
- }
- sem_t *Sem_open(const char *name, int oflag,
- mode_t mode, unsigned int value)
- {
- sem_t *sem = sem_open(name, oflag, mode, value);
- if( NULL == sem )
- error_quit("sem_open error for %s", name);
- return sem;
- }
- void Sem_close(sem_t *sem)
- {
- if (sem_close(sem) == -1)
- error_quit("sem_close error");
- }
- void Sem_unlink(const char *pathname)
- {
- if (sem_unlink(pathname) == -1)
- error_quit("sem_unlink error");
- }
- void Sem_init(sem_t *sem, int pshared, unsigned int value)
- {
- if (sem_init(sem, pshared, value) == -1)
- error_quit("sem_init error");
- }
- void Sem_destroy(sem_t *sem)
- {
- if (sem_destroy(sem) == -1)
- error_quit("sem_destroy error");
- }
- void Sem_wait(sem_t *sem)
- {
- if (sem_wait(sem) == -1)
- error_quit("sem_wait error");
- }
- void Sem_post(sem_t *sem)
- {
- if (sem_post(sem) == -1)
- error_quit("sem_post error");
- }
- void Sem_getvalue(sem_t *sem, int *valp)
- {
- if (sem_getvalue(sem, valp) == -1)
- error_quit("sem_getvalue error");
- }