《UNIX网络编程》例子程序中所使用的 包裹函数 及 部分常量

转载地址:http://blog.chinaunix.net/uid-28977986-id-3886809.html


    《UNIX网络编程套接字联网API》这本书的示例中定义了许多包裹函数,它们的名称和标准函数一样,只是首字母变成大写字母;每个包裹函数完成实际的函数调用,检查返回值,并在发生错误时终止程序。

我在重写书上例子的时候,也仿照书上的方式,定义了许多包裹函数,提高程序的可读性(当然,我定义的包裹函数的错误处理没有书上例子这么详细了)

文件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"); 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值