《UNIX网络编程套接字联网API》这本书的示例中定义了许多包裹函数,它们的名称和标准函数一样,只是首字母变成大写字母;每个包裹函数完成实际的函数调用,检查返回值,并在发生错误时终止程序。
我在重写书上例子的时候,也仿照书上的方式,定义了许多包裹函数,提高程序的可读性(当然,我定义的包裹函数的错误处理没有书上例子这么详细了)
文件my_unp.h:它定义了一些常量,声明了所有的包裹函数
-
[cpp] view plaincopyprint?
-
#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");
-
}