Chinaunix首页 | 论坛 | 博客
  • 博客访问: 541775
  • 博文数量: 129
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1888
  • 用 户 组: 普通用户
  • 注册时间: 2013-06-20 11:09
文章分类

全部博文(129)

文章存档

2016年(1)

2015年(5)

2014年(64)

2013年(59)

我的朋友

分类: LINUX

2013-09-05 17:56:13

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

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

文件my_unp.h:它定义了一些常量,声明了所有的包裹函数

  1. [cpp] view plaincopyprint?
  2. #ifndef MY_UNP_H_
  3. #define MY_UNP_H_
  4.   
  5. #include <stdio.h>
  6. #include <stdarg.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <time.h>
  10.   
  11. #include <unistd.h>
  12. #include <errno.h>
  13. #include <pthread.h>
  14. #include <semaphore.h>
  15. #include <sys/socket.h>
  16. #include <sys/wait.h>
  17. #include <netinet/in.h>
  18. #include <arpa/inet.h>
  19. #include <sys/select.h>
  20. #include <sys/epoll.h>
  21. #include <sys/poll.h>
  22. #include <sys/file.h>
  23. #include <sys/mman.h>
  24.   
  25. #define MAXLINE 1024
  26. #define LISTENQ 1024
  27.   
  28. #define MAXNITEMS 1000000
  29. #define MAXNTHREADS 100
  30.   
  31. #define SERV_PORT 9877
  32. #define SERV_PORT_STR "9877"
  33.   
  34. #define SA struct sockaddr
  35. typedef void Sigfunc(int);
  36.   
  37. #define min(a,b) ((a) < (b) ? (a) : (b))
  38. #define max(a,b) ((a) > (b) ? (a) : (b))
  39.   
  40.   
  41. //错误处理函数,输出错误信息后退出程序
  42. void error_quit(char *fmt, ...);
  43.   
  44. //为了适应网络的慢速IO而编写的读写函数
  45. ssize_t readn(int fd, void *vptr, size_t n);
  46. ssize_t writen(int fd, const void *vptr, size_t n);
  47. ssize_t readline(int fd, void *vptr, size_t maxlen);
  48.   
  49. //各类读写包裹函数
  50. void Write(int fd, void *ptr, size_t nbytes);
  51. ssize_t Read(int fd, void *ptr, size_t nbytes);
  52. ssize_t Readn(int fd, void *ptr, size_t nbytes);
  53. void Writen(int fd, void *ptr, size_t nbytes);
  54. ssize_t Readline(int fd, void *ptr, size_t maxlen);
  55. void Fputs(const char *ptr, FILE *stream);
  56. char *Fgets(char *ptr, int n, FILE *stream);
  57.   
  58. //各类标准包裹函数
  59. int Open(const char *pathname, int flags, mode_t mode);
  60. void Close(int fd);
  61. Sigfunc *Signal(int signo, Sigfunc *func);
  62. void *Malloc(size_t size);
  63. void *Calloc(size_t n, size_t size);
  64. void Pipe(int *fds);
  65. pid_t Fork(void);
  66. pid_t Waitpid(pid_t pid, int *iptr, int options);
  67. void Dup2(int fd1, int fd2);
  68.   
  69. //各类网络包裹函数
  70. int Socket(int family, int type, int protocol);
  71. void Inet_pton(int family, const char *strptr, void *addrptr);
  72. void Connect(int fd, const struct sockaddr *sa, socklen_t salen);
  73. void Listen(int fd, int backlog);
  74. void Bind(int fd, const struct sockaddr *sa, socklen_t salen);
  75. int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
  76. const char *Inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
  77. int Select(int nfds, fd_set *readfds, fd_set *writefds,
  78.            fd_set *exceptfds, struct timeval *timeout);
  79. int Poll(struct pollfd *fdarray, unsigned long nfds, int timeout);
  80. void Shutdown(int fd, int how);
  81. int Epoll_create(int size);
  82. void Epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
  83. int Epoll_wait(int epfd, struct epoll_event *events,
  84.                int maxevents, int timeout);
  85. void Sendto(int fd, const void *ptr, size_t nbytes, int flags,
  86.             const struct sockaddr *sa, socklen_t salen);
  87. ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags,
  88.                 struct sockaddr *sa, socklen_t *salenptr);
  89. void Setsockopt(int fd, int level, int optname,
  90.                 const void *optval, socklen_t optlen);
  91. void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
  92. void Munmap(void *addr, size_t len);
  93. void Ftruncate(int fd, off_t length);
  94.   
  95. //各类和线程操作相关的包裹函数
  96. void Pthread_create(pthread_t *tid, const pthread_attr_t *attr,
  97.                     void * (*func)(void *), void *arg);
  98. void Pthread_detach(pthread_t tid);
  99. void Pthread_join(pthread_t tid, void **status);
  100. void Pthread_kill(pthread_t tid, int signo);
  101. void Pthread_mutex_lock(pthread_mutex_t *mptr);
  102. void Pthread_mutex_unlock(pthread_mutex_t *mptr);
  103. //此函数相当于UNP书上的set_concurrency函数
  104. void Pthread_setconcurrency(int level);
  105. void Pthread_cond_signal(pthread_cond_t *cptr);
  106. void Pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr);
  107.   
  108. //各类和信号量相关的包裹函数
  109. sem_t *Sem_open(const char *name, int oflag,
  110.                 mode_t mode, unsigned int value);
  111. void Sem_close(sem_t *sem);
  112. void Sem_unlink(const char *pathname);
  113. void Sem_init(sem_t *sem, int pshared, unsigned int value);
  114. void Sem_destroy(sem_t *sem);
  115. void Sem_wait(sem_t *sem);
  116. void Sem_post(sem_t *sem);
  117. void Sem_getvalue(sem_t *sem, int *valp);
  118.   
  119. #endif


文件unp_base.c:它定义了基本的包裹函数


  1. #include "my_unp.h"
  2.   
  3. //此函数是在程序发生错误时被调用
  4. //先输出字符串fmt,再根据errno输出错误原因(如果有的话),最后退出程序
  5. //注:在多线程程序中,错误原因可能不正确
  6. void error_quit(char *fmt, ...)
  7. {
  8.     int res;
  9.     va_list list;
  10.     va_start(list, fmt);
  11.     res = vfprintf(stderr, fmt, list);
  12.     if( errno != 0 )
  13.         fprintf(stderr, " : %s", strerror(errno));
  14.     fprintf(stderr, "\n", list);
  15.     va_end(list);
  16.     exit(1);
  17. }
  18.   
  19. //字节流套接字上调用read时,输入的字节数可能比请求的数量少,
  20. //但这不是出错的状态,原因是内核中用于套接字的缓冲区可能已经达到了极限,
  21. //此时需要调用者再次调用read函数
  22. ssize_t readn(int fd, void *vptr, size_t n)
  23. {
  24.     size_t nleft;
  25.     ssize_t nread;
  26.     char *ptr;
  27.   
  28.     ptr = vptr;
  29.     nleft = n;
  30.     while (nleft > 0)
  31.     {
  32.         if ( (nread = read(fd, ptr, nleft)) < 0)
  33.         {
  34.             if (errno == EINTR)
  35.                 nread = 0; /* and call read() again */
  36.             else
  37.                 return(-1);
  38.         }
  39.         else if (nread == 0)
  40.             break; /* EOF */
  41.         nleft -= nread;
  42.         ptr += nread;
  43.     }
  44.     return (n - nleft); /* return >= 0 */
  45. }
  46.   
  47. //字节流套接字上调用write时,输出的字节数可能比请求的数量少,
  48. //但这不是出错的状态,原因是内核中用于套接字的缓冲区可能已经达到了极限,
  49. //此时需要调用者再次调用write函数
  50. ssize_t writen(int fd, const void *vptr, size_t n)
  51. {
  52.     size_t nleft;
  53.     ssize_t nwritten;
  54.     const char *ptr;
  55.   
  56.     ptr = vptr;
  57.     nleft = n;
  58.     while (nleft > 0)
  59.     {
  60.         if ( (nwritten = write(fd, ptr, nleft)) <= 0)
  61.         {
  62.             if (nwritten < 0 && errno == EINTR)
  63.                 nwritten = 0; /* and call write() again */
  64.             else
  65.                 return(-1); /* error */
  66.         }
  67.         nleft -= nwritten;
  68.         ptr += nwritten;
  69.     }
  70.     return n;
  71. }
  72.   
  73. static int read_cnt;
  74. static char *read_ptr;
  75. static char read_buf[MAXLINE];
  76.   
  77. //内部函数my_read每次最多读MAXLINE个字节,然后每次返回一个字节
  78. static ssize_t my_read(int fd, char *ptr)
  79. {
  80.     if (read_cnt <= 0)
  81.     {
  82. again:
  83.         if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0)
  84.         {
  85.             if (errno == EINTR)
  86.                 goto again;
  87.             return(-1);
  88.         }
  89.         else if (read_cnt == 0)
  90.             return(0);
  91.         read_ptr = read_buf;
  92.     }
  93.   
  94.     read_cnt--;
  95.     *ptr = *read_ptr++;
  96.     return 1;
  97. }
  98.   
  99. //从描述符中读取文本行
  100. ssize_t readline(int fd, void *vptr, size_t maxlen)
  101. {
  102.     ssize_t n, rc;
  103.     char c, *ptr;
  104.   
  105.     ptr = vptr;
  106.     for (n = 1; n < maxlen; n++)
  107.     {
  108.         if ( (rc = my_read(fd, &c)) == 1)
  109.         {
  110.             *ptr++ = c;
  111.             if (c == '\n')
  112.                 break; /* newline is stored, like fgets() */
  113.         }
  114.         else if (rc == 0)
  115.         {
  116.             *ptr = 0;
  117.             return(n - 1); /* EOF, n - 1 bytes were read */
  118.         }
  119.         else
  120.             return(-1); /* error, errno set by read() */
  121.     }
  122.     *ptr = 0; /* null terminate like fgets() */
  123.     return n;
  124. }
  125.   
  126. ssize_t Readn(int fd, void *ptr, size_t nbytes)
  127. {
  128.     ssize_t n = readn(fd, ptr, nbytes);
  129.     if ( n < 0)
  130.         error_quit("readn error");
  131.     return n;
  132. }
  133.   
  134. void Writen(int fd, void *ptr, size_t nbytes)
  135. {
  136.     if ( writen(fd, ptr, nbytes) != nbytes )
  137.         error_quit("writen error");
  138. }
  139.   
  140. ssize_t Readline(int fd, void *ptr, size_t maxlen)
  141. {
  142.     ssize_t n = readline(fd, ptr, maxlen);
  143.     if ( n < 0)
  144.         error_quit("readline error");
  145.     return n;
  146. }
  147.   
  148. ssize_t Read(int fd, void *ptr, size_t nbytes)
  149. {
  150.     ssize_t n = read(fd, ptr, nbytes);
  151.     if ( n == -1)
  152.         error_quit("read error");
  153.     return n;
  154. }
  155.   
  156. void Write(int fd, void *ptr, size_t nbytes)
  157. {
  158.     if (write(fd, ptr, nbytes) != nbytes)
  159.         error_quit("write error");
  160. }
  161.   
  162. int Open(const char *pathname, int flags, mode_t mode)
  163. {
  164.     int fd = open(pathname, flags, mode);
  165.     if( -1 == fd )
  166.         error_quit("open file %s error", pathname);
  167.     return fd;
  168. }
  169.   
  170. void Close(int fd)
  171. {
  172.     if (close(fd) == -1)
  173.         error_quit("close error");
  174. }
  175.   
  176. void Fputs(const char *ptr, FILE *stream)
  177. {
  178.     if (fputs(ptr, stream) == EOF)
  179.         error_quit("fputs error");
  180. }
  181.   
  182. char *Fgets(char *ptr, int n, FILE *stream)
  183. {
  184.     char *rptr = fgets(ptr, n, stream);
  185.     if ( rptr == NULL && ferror(stream) )
  186.         error_quit("fgets error");
  187.     return rptr;
  188. }
  189.   
  190. int Socket(int family, int type, int protocol)
  191. {
  192.     int n = socket(family, type, protocol);
  193.     if( n < 0)
  194.         error_quit("socket error");
  195.     return n;
  196. }
  197.   
  198. void Inet_pton(int family, const char *strptr, void *addrptr)
  199. {
  200.     int n = inet_pton(family, strptr, addrptr);
  201.     if( n < 0)
  202.         error_quit("inet_pton error for %s", strptr);
  203. }
  204.   
  205. void Connect(int fd, const struct sockaddr *sa, socklen_t salen)
  206. {
  207.     if (connect(fd, sa, salen) < 0)
  208.         error_quit("connect error");
  209. }
  210.   
  211. void Listen(int fd, int backlog)
  212. {
  213.     if (listen(fd, backlog) < 0)
  214.         error_quit("listen error");
  215. }
  216.   
  217. void Bind(int fd, const struct sockaddr *sa, socklen_t salen)
  218. {
  219.     if (bind(fd, sa, salen) < 0)
  220.         error_quit("bind error");
  221. }
  222.   
  223. int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
  224. {
  225.     int n = accept(fd, sa, salenptr);
  226.     if ( n < 0)
  227.         error_quit("accept error");
  228.     return n;
  229. }
  230.   
  231. const char *Inet_ntop(int family, const void *addrptr, char *strptr, size_t len)
  232. {
  233.     const char *ptr = inet_ntop(family, addrptr, strptr, len);
  234.     if ( ptr == NULL)
  235.         error_quit("inet_ntop error");
  236.     return ptr;
  237. }
  238.   
  239. pid_t Fork(void)
  240. {
  241.     pid_t pid = fork();
  242.     if ( pid == -1)
  243.         error_quit("fork error");
  244.     return pid;
  245. }
  246.   
  247. Sigfunc *Signal(int signo, Sigfunc *func)
  248. {
  249.     Sigfunc *sigfunc = signal(signo, func);
  250.     if ( sigfunc == SIG_ERR)
  251.         error_quit("signal error");
  252.     return sigfunc;
  253. }
  254.   
  255. int Select(int nfds, fd_set *readfds, fd_set *writefds,
  256.            fd_set *exceptfds, struct timeval *timeout)
  257. {
  258.     int n = select(nfds, readfds, writefds, exceptfds, timeout);
  259.     if ( n < 0 )
  260.         error_quit("select error");
  261.     return n; /* can return 0 on timeout */
  262. }
  263.   
  264. int Poll(struct pollfd *fdarray, unsigned long nfds, int timeout)
  265. {
  266.     int n = poll(fdarray, nfds, timeout);
  267.     if ( n < 0 )
  268.         error_quit("poll error");
  269.     return n;
  270. }
  271.   
  272. void Shutdown(int fd, int how)
  273. {
  274.     if (shutdown(fd, how) < 0)
  275.         error_quit("shutdown error");
  276. }
  277.   
  278. int Epoll_create(int size)
  279. {
  280.     int n = epoll_create(size);
  281.     if( n < 0 )
  282.         error_quit("epoll create error");
  283.     return n;
  284. }
  285.   
  286. void Epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
  287. {
  288.     if( epoll_ctl(epfd, op, fd, event) < 0 )
  289.         error_quit("epoll ctl error");
  290. }
  291.   
  292. int Epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
  293. {
  294.     int n = epoll_wait(epfd, events, maxevents, timeout);
  295.     if( n < 0 )
  296.         error_quit("epoll wait error");
  297.     return n;
  298. }
  299.   
  300. void Sendto(int fd, const void *ptr, size_t nbytes, int flags,
  301.             const struct sockaddr *sa, socklen_t salen)
  302. {
  303.     if (sendto(fd, ptr, nbytes, flags, sa, salen) != (ssize_t)nbytes)
  304.         error_quit("sendto error");
  305. }
  306.   
  307. ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags,
  308. struct sockaddr *sa, socklen_t *salenptr)
  309. {
  310.     ssize_t n = recvfrom(fd, ptr, nbytes, flags, sa, salenptr);
  311.     if ( n < 0 )
  312.         error_quit("recvfrom error");
  313.     return n;
  314. }
  315.   
  316. ssize_t Recvmsg(int fd, struct msghdr *msg, int flags)
  317. {
  318.     ssize_t n = recvmsg(fd, msg, flags);
  319.     if ( n < 0 )
  320.         error_quit("recvmsg error");
  321.     return(n);
  322. }
  323.   
  324. void *Malloc(size_t size)
  325. {
  326.     void *ptr = malloc(size);
  327.     if ( ptr == NULL )
  328.         error_quit("malloc error");
  329.     return ptr;
  330. }
  331.   
  332. void *Calloc(size_t n, size_t size)
  333. {
  334.     void *ptr = calloc(n, size);
  335.     if ( ptr == NULL)
  336.         error_quit("calloc error");
  337.     return ptr;
  338. }
  339.   
  340. void Pipe(int *fds)
  341. {
  342.     if ( pipe(fds) < 0 )
  343.         error_quit("pipe error");
  344. }
  345.   
  346. pid_t Waitpid(pid_t pid, int *iptr, int options)
  347. {
  348.     pid_t retpid = waitpid(pid, iptr, options);
  349.     if ( retpid == -1)
  350.         error_quit("waitpid error");
  351.     return retpid;
  352. }
  353.   
  354. void Setsockopt(int fd, int level, int optname,
  355.                 const void *optval, socklen_t optlen)
  356. {
  357.     if (setsockopt(fd, level, optname, optval, optlen) < 0)
  358.         error_quit("setsockopt error");
  359. }
  360.   
  361. void Socketpair(int family, int type, int protocol, int *fd)
  362. {
  363.     int n = socketpair(family, type, protocol, fd);
  364.     if ( n < 0 )
  365.         error_quit("socketpair error");
  366. }
  367.   
  368. void Dup2(int fd1, int fd2)
  369. {
  370.     if (dup2(fd1, fd2) == -1)
  371.         error_quit("dup2 error");
  372. }
  373.   
  374. void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
  375. {
  376.     void *ptr = mmap(addr, len, prot, flags, fd, offset);
  377.     if ( ptr == MAP_FAILED )
  378.         error_quit("mmap error");
  379.     return ptr;
  380. }
  381.   
  382. void Munmap(void *addr, size_t len)
  383. {
  384.     if (munmap(addr, len) == -1)
  385.         error_quit("munmap error");
  386. }
  387.   
  388. void Ftruncate(int fd, off_t length)
  389. {
  390.     if (ftruncate(fd, length) == -1)
  391.         error_quit("ftruncate error");
  392. }

文件unp_pthread.c:它定义了基本的线程类包裹函数

  1. #include "my_unp.h"
  2.   
  3. void Pthread_create(pthread_t *tid, const pthread_attr_t *attr,
  4.                     void * (*func)(void *), void *arg)
  5. {
  6.     int n = pthread_create(tid, attr, func, arg);
  7.     if ( n == 0)
  8.         return;
  9.     errno = n;
  10.     error_quit("pthread_create error");
  11. }
  12.   
  13. void Pthread_detach(pthread_t tid)
  14. {
  15.     int n = pthread_detach(tid);
  16.     if ( n == 0)
  17.         return;
  18.     errno = n;
  19.     error_quit("pthread_detach error");
  20. }
  21.   
  22. void Pthread_join(pthread_t tid, void **status)
  23. {
  24.     int n = pthread_join(tid, status);
  25.     if ( n == 0 )
  26.         return;
  27.     errno = n;
  28.     error_quit("pthread_join error");
  29. }
  30.   
  31. void Pthread_kill(pthread_t tid, int signo)
  32. {
  33.     int n = pthread_kill(tid, signo);
  34.     if ( n == 0 )
  35.         return;
  36.     errno = n;
  37.     error_quit("pthread_kill error");
  38. }
  39.   
  40. void Pthread_mutex_lock(pthread_mutex_t *mptr)
  41. {
  42.     int n = pthread_mutex_lock(mptr);
  43.     if ( n == 0 )
  44.         return;
  45.     errno = n;
  46.     error_quit("pthread_mutex_lock error");
  47. }
  48.   
  49. void Pthread_mutex_unlock(pthread_mutex_t *mptr)
  50. {
  51.     int n = pthread_mutex_unlock(mptr);
  52.     if ( n == 0 )
  53.         return;
  54.     errno = n;
  55.     error_quit("pthread_mutex_unlock error");
  56. }
  57.   
  58. void Pthread_setconcurrency(int level)
  59. {
  60.     int n = pthread_setconcurrency(level);
  61.     if ( n == 0 )
  62.         return;
  63.     errno = n;
  64.     error_quit("pthread_mutex_unlock error");
  65. }
  66.   
  67. void Pthread_cond_signal(pthread_cond_t *cptr)
  68. {
  69.     int n = pthread_cond_signal(cptr);
  70.     if ( n == 0 )
  71.         return;
  72.     errno = n;
  73.     error_quit("pthread_cond_signal error");
  74. }
  75.   
  76. void Pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr)
  77. {
  78.     int n = pthread_cond_wait(cptr, mptr);
  79.     if ( n == 0 )
  80.         return;
  81.     errno = n;
  82.     error_quit("pthread_cond_wait error");
  83. }
  84.   
  85. sem_t *Sem_open(const char *name, int oflag,
  86.                 mode_t mode, unsigned int value)
  87. {
  88.     sem_t *sem = sem_open(name, oflag, mode, value);
  89.     if( NULL == sem )
  90.         error_quit("sem_open error for %s", name);
  91.     return sem;
  92. }
  93.   
  94. void Sem_close(sem_t *sem)
  95. {
  96.     if (sem_close(sem) == -1)
  97.         error_quit("sem_close error");
  98. }
  99.   
  100. void Sem_unlink(const char *pathname)
  101. {
  102.     if (sem_unlink(pathname) == -1)
  103.         error_quit("sem_unlink error");
  104. }
  105.   
  106. void Sem_init(sem_t *sem, int pshared, unsigned int value)
  107. {
  108.     if (sem_init(sem, pshared, value) == -1)
  109.         error_quit("sem_init error");
  110. }
  111.   
  112. void Sem_destroy(sem_t *sem)
  113. {
  114.     if (sem_destroy(sem) == -1)
  115.         error_quit("sem_destroy error");
  116. }
  117.   
  118. void Sem_wait(sem_t *sem)
  119. {
  120.     if (sem_wait(sem) == -1)
  121.         error_quit("sem_wait error");
  122. }
  123.   
  124. void Sem_post(sem_t *sem)
  125. {
  126.     if (sem_post(sem) == -1)
  127.         error_quit("sem_post error");
  128. }
  129.   
  130. void Sem_getvalue(sem_t *sem, int *valp)
  131. {
  132.     if (sem_getvalue(sem, valp) == -1)
  133.         error_quit("sem_getvalue error");
  134. }





阅读(1487) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~