• 学习 UNIX网络编程卷1:套接字 笔记1-实现一个简单的回射客户服务器程序


    一:客户端程序

    1、头文件:unp.h

     1 #ifndef _unp_h
     2 #define _unp_h
     3 #include <sys/types.h> /* basic system data types */
     4 #include <sys/socket.h> /* basic socket definitions */
     5 #include <sys/time.h> /* timeval{} for select() */
     6 #include <time.h>  /* timespec{} for pselect() */
     7 #include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
     8 #include <arpa/inet.h> /* inet(3) functions */
     9 #include <errno.h>
    10 #include <fcntl.h>  /* for nonblocking */
    11 #include <netdb.h>
    12 #include <signal.h>
    13 #include <stdio.h>
    14 #include <stdlib.h>
    15 #include <string.h>
    16 #include <sys/stat.h> /* for S_xxx file mode constants */
    17 #include <sys/uio.h>  /* for iovec{} and readv/writev */
    18 #include <unistd.h>
    19 #include <sys/wait.h>
    20 #include <sys/un.h>  /* for Unix domain sockets */
    21 #define MAXLINE 4096
    22 #define LISTENQ 5
    23 #define SERV_PORT   9877
    24 int Socket(int sockfd, int type, int protocol);
    25 void Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
    26 void Listen(int sockfd,int backlog);
    27 void Connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
    28 int Accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
    29 void Write(int fd,void *buf,size_t count);
    30 void Close(int sockfd);
    31 void err_sys(char *err_str);
    32 int Fork();
    33 void str_echo(int sockfd);
    34 ssize_t writen(int fd, char *buf, size_t n);
    35 ssize_t Writen(int fd, char *buf, size_t n);
    36 void str_cli(FILE *fp, int sockfd);
    37 ssize_t readline(int fd, void *vptr, size_t maxlen);
    38 ssize_t Readline(int fd, void *vptr, size_t maxlen);
    39 #endif

    2、客户端主程序:clien.c

     1 #include "unp.h"
     2 
     3 int main(int argc,char **argv)
     4 {
     5     char ip_addr[20];
     6     int sockfd;
     7     struct sockaddr_in servaddr;
     8     /**add for ipaddress **/
     9     /*
    10     if (argc != 2)
    11     {
    12         err_sys("usage:clien <IPaddress>");
    13         return -1;
    14     }
    15     */
    16 
    17     bzero(&servaddr, sizeof(servaddr));
    18     bzero(ip_addr,sizeof(ip_addr));
    19     /**add for ipaddress**/
    20     //strcpy(ip_addr,argv[1]);
    21     sockfd = Socket(AF_INET, SOCK_STREAM, 0);
    22 
    23     servaddr.sin_family = AF_INET;
    24     servaddr.sin_port = htons(SERV_PORT);
    25     servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    26     //servaddr.sin_addr.s_addr = inet_addr(ip_addr);
    27     Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    28 
    29     str_cli(stdin,sockfd);
    30 
    31     return 0;
    32 
    33 }

    3、客户端包裹函数:pack.c

     1 #include "unp.h"
     2 
     3 void err_sys(char *err_str)
     4 {
     5   perror(err_str);
     6 }
     7 
     8 int Socket(int sockfd, int type, int protocol)
     9 {
    10   int n=0;
    11   if ((n=socket(sockfd,type,protocol))<0)
    12   {
    13     err_sys("socket error");
    14   }
    15   return n;
    16 }
    17 
    18 void Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
    19 {
    20   int n=0;
    21   if ((n = bind(sockfd,myaddr,addrlen))<0)
    22   {
    23     err_sys("bind error");
    24   }
    25 }
    26 
    27 void Listen(int sockfd,int backlog)
    28 {
    29   char *ptr=NULL;
    30   if ((ptr=getenv("LISTENQ"))!=NULL)
    31   {
    32     backlog=atoi(ptr);
    33   }
    34   if (listen(sockfd,backlog)<0)
    35   {
    36     err_sys("listen error");
    37   }
    38 }
    39 
    40 void Connect(int sockfd,const struct sockaddr *servaddr, socklen_t addrlen)
    41 {
    42   if(connect(sockfd,servaddr,addrlen)<0)
    43   {
    44     err_sys("connect error");
    45   }
    46   else
    47   {
    48     printf("connect success!
    ");
    49   }
    50 }
    51 
    52 int Accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)
    53 {
    54   int n;
    55   again:
    56     if ((n=accept(sockfd,cliaddr,addrlen))<0)
    57     {
    58 #ifndef EPROTO
    59       if(errno == EPROTO || errno == ECONNABORTED)
    60 #else
    61       if(errno == ECONNABORTED)
    62 #endif
    63       {
    64           goto again;
    65       }
    66       else
    67       {
    68         err_sys("accept error");
    69       }
    70     }
    71   return n;
    72 }
    73 
    74 ssize_t Writen(int fd,char *buf, size_t n)
    75 {
    76   ssize_t ret;
    77   ret = writen(fd,buf,n);
    78   if (ret < 0)
    79   {
    80     err_sys("writen error");
    81     return -1;
    82   }
    83   return ret;
    84 }
    85 
    86 ssize_t Readline(int fd, void *vptr, size_t maxlen)
    87 {
    88   ssize_t n;
    89   n=readline(fd,vptr,maxlen);
    90   if (n<0)
    91   {
    92     err_sys("readline error");
    93     return -1;
    94   }
    95   return n;
    96 }

    4、客户端功能行函数:func.c

     1 #include "unp.h"
     2 ssize_t writen(int fd, char *buf, size_t n)
     3 {
     4   size_t nleft;
     5   ssize_t nwritten;
     6   char *ptr;
     7   ptr = buf;
     8   nleft = n ;
     9   while(nleft > 0)
    10   {
    11     nwritten = write(fd, ptr, nleft);
    12     if (nwritten < 0 && errno == EINTR)
    13     {
    14       nwritten = 0;      
    15     }
    16     else if (nwritten < 0)
    17     {
    18       err_sys("write error");
    19       return -1;
    20     }
    21 
    22     nleft -= nwritten;
    23     ptr += nwritten;
    24   }
    25   return n;
    26 }
    27 
    28 void str_echo(int sockfd)
    29 {
    30   ssize_t n;
    31   char buf[MAXLINE];
    32   again:
    33     while ((n = read(sockfd, buf, MAXLINE))>0)
    34       Writen(sockfd, buf, n);
    35   if (n < 0 && errno == EINTR)
    36   {
    37     goto again;
    38   }
    39   else if (n < 0)
    40   {
    41     err_sys("str_echo error");
    42   }
    43 }
    44 ssize_t readline(int fd, void *vptr, size_t maxlen)
    45 {
    46     ssize_t n,rc;
    47     char c,*ptr;
    48     ptr = vptr;
    49     for (n = 1; n < maxlen; n++)
    50     {
    51         again:
    52             if ((rc = read(fd, &c, 1)) == 1)
    53             {
    54                 *ptr++ = c;
    55                 if (c == '
    ')
    56                 {
    57                     break;
    58                 }
    59             }
    60             else if (rc == 0)
    61             {
    62                 *ptr = 0;
    63                 return (n-1);
    64             }
    65             else
    66             {
    67                 if (errno == EINTR)        
    68                 {
    69                     goto again;
    70                 }
    71                 return -1;
    72             }
    73     }
    74     *ptr = 0;
    75     return n;
    76 }
    77 
    78 void str_cli(FILE *fp, int sockfd)
    79 {
    80     char sendline[MAXLINE],recvline[MAXLINE];
    81     bzero(sendline,sizeof(sendline));
    82     bzero(recvline,sizeof(recvline));
    83 
    84     while(fgets(sendline,MAXLINE,fp) != NULL)
    85     {
    86         Writen(sockfd,sendline,strlen(sendline));
    87         if (Readline(sockfd, recvline, MAXLINE) == 0)
    88         {
    89             err_sys("str_cli Readline error");
    90         }
    91         fputs(recvline, stdout);
    92     }
    93 }

    5、客户端Makefile

     1 clien:clien.o pack.o func.o
     2     gcc clien.o pack.o func.o -o clien
     3 clien.o:clien.c unp.h 
     4     gcc -c clien.c -o clien.o
     5 pack.o:pack.c unp.h 
     6     gcc -c pack.c -o pack.o
     7 func.o:func.c unp.h 
     8     gcc -c func.c -o func.o    
     9 .PHONY:clean
    10 clean:
    11     rm -f *.o

    二:服务器程序

    1、头文件:unp.h

     1 #ifndef _unp_h
     2 #define _unp_h
     3 #include <sys/types.h> /* basic system data types */
     4 #include <sys/socket.h> /* basic socket definitions */
     5 #include <sys/time.h> /* timeval{} for select() */
     6 #include <time.h>  /* timespec{} for pselect() */
     7 #include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
     8 #include <arpa/inet.h> /* inet(3) functions */
     9 #include <errno.h>
    10 #include <fcntl.h>  /* for nonblocking */
    11 #include <netdb.h>
    12 #include <signal.h>
    13 #include <stdio.h>
    14 #include <stdlib.h>
    15 #include <string.h>
    16 #include <sys/stat.h> /* for S_xxx file mode constants */
    17 #include <sys/uio.h>  /* for iovec{} and readv/writev */
    18 #include <unistd.h>
    19 #include <sys/wait.h>
    20 #include <sys/un.h>  /* for Unix domain sockets */
    21 #define MAXLINE 4096
    22 #define LISTENQ 5
    23 #define SERV_PORT   9877
    24 typedef void (*sighandler_t)(int);
    25 sighandler_t Signal(int signum, sighandler_t handler);
    26 int Socket(int sockfd, int type, int protocol);
    27 void Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
    28 void Listen(int sockfd,int backlog);
    29 void Connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
    30 int Accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
    31 void Write(int fd,void *buf,size_t count);
    32 void Close(int sockfd);
    33 void err_sys(char *err_str);
    34 int Fork();
    35 void str_echo(int sockfd);
    36 ssize_t writen(int fd, char *buf, size_t n);
    37 ssize_t Writen(int fd, char *buf, size_t n);
    38 void sig_chlid(int signo);
    39 #endif

    2、服务器主程序:serv.c

     1 #include "unp.h"
     2 void sig_chld(int );
     3 
     4 int main(int argc, char const *argv[])
     5 {
     6     int listenfd,connfd;
     7     pid_t childpid;
     8     socklen_t clilen;
     9     struct sockaddr_in cliaddr,servaddr;
    10     listenfd = Socket(AF_INET, SOCK_STREAM, 0);//监听套接字创建
    11     bzero(&servaddr, sizeof(servaddr));
    12     servaddr.sin_family = AF_INET;//服务器地址族
    13     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//服务器地址赋值,一般服务器地址不指定
    14     servaddr.sin_port = htons(SERV_PORT);//服务器端口赋值
    15     Bind(listenfd,(struct sockaddr*)&servaddr, sizeof(servaddr));//绑定监听套接字与服务器的端口
    16     Listen(listenfd, LISTENQ);  //监听
    17     Signal(SIGCHLD, sig_chld);  //回收僵死子进程
    18     while(1)
    19     {
    20         clilen = sizeof(cliaddr);
    21         connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);//accept创建已连接套接字connfd
    22         if (connfd<0) {
    23           if(errno == EINTR)//处理系统中断
    24           {
    25             continue;
    26           }
    27           else
    28           {
    29             err_sys("accept error");
    30           }
    31         }
    32         if ((childpid = Fork()) == 0)//创建子进程
    33         {
    34             Close(listenfd);//子进程关闭监听套接字
    35             str_echo(connfd);//调用回射函数
    36             exit(0);
    37         }
    38         else//父进程
    39         {
    40             Close(connfd);//父进程关闭已连接套接字
    41         }
    42 
    43     }
    44     return 0;
    45 }

    3、包裹函数:pack.c

      1 #include "unp.h"
      2 
      3 void err_sys(char *err_str)
      4 {
      5   perror(err_str);
      6 }
      7 
      8 int Socket(int sockfd, int type, int protocol)
      9 {
     10   int n=0;
     11   if ((n=socket(sockfd,type,protocol))<0)
     12   {
     13     err_sys("socket error");
     14   }
     15   printf("socket success!sockfd=%d
    ",n);
     16   return n;
     17 }
     18 
     19 void Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
     20 {
     21   int n=0;
     22   if ((n = bind(sockfd,myaddr,addrlen))<0)
     23   {
     24     err_sys("bind error");
     25   }
     26   printf("bind success
    ");
     27 }
     28 
     29 void Listen(int sockfd,int backlog)
     30 {
     31   char *ptr=NULL;
     32   if ((ptr=getenv("LISTENQ"))!=NULL)
     33   {
     34     backlog=atoi(ptr);
     35   }
     36   if (listen(sockfd,backlog)<0)
     37   {
     38     err_sys("listen error");
     39   }
     40   printf("listen success
    ");
     41 }
     42 
     43 void Connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen)
     44 {
     45   if(connect(sockfd,servaddr,addrlen)<0)
     46   {
     47     err_sys("connect error");
     48   }
     49   printf("connect success!
    ");
     50 }
     51 
     52 int Accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)
     53 {
     54   int n;
     55   again:
     56     if ((n=accept(sockfd,cliaddr,addrlen))<0)
     57     {
     58 #ifndef EPROTO
     59       if(errno == EPROTO || errno == ECONNABORTED)
     60 #else
     61       if(errno == ECONNABORTED)
     62 #endif
     63       {
     64           goto again;
     65       }
     66       else
     67       {
     68         err_sys("accept error");
     69       }
     70     }
     71   return n;
     72 }
     73 
     74 /*
     75 char* Inet_ntop(int family, const void *addrptr,char *strptr,size_t len)
     76 {
     77   char buff[1024+1];
     78   bzero(buff,sizeof(buff));
     79   if(inet_ntop(family,addrptr,strptr,len)==NULL)
     80   {
     81     err_sys("inet_error");
     82   }
     83   strcpy(buff,strptr);
     84   return buff;
     85 }
     86 */
     87 void Write(int fd,void *buf,size_t count)
     88 {
     89     ssize_t n;
     90     n=write(fd,buf,count);
     91     if(n!=count)
     92     {
     93         err_sys("write error");
     94     }
     95 
     96 }
     97 void Close(int sockfd)
     98 {
     99     if(close(sockfd)==-1)
    100     {
    101         err_sys("close error");
    102     }
    103 }
    104 
    105 int Fork()
    106 {
    107   pid_t pid;
    108   if ((pid = fork()) < 0)
    109   {
    110     err_sys("fork error");
    111   }
    112   else
    113     return pid;
    114 }
    115 
    116 ssize_t Writen(int fd,char *buf, size_t n)
    117 {
    118   ssize_t ret;
    119   ret = writen(fd,buf,n);
    120   if (ret < 0)
    121   {
    122     err_sys("writen error");
    123     return -1;
    124   }
    125   return ret;
    126 }
    127 
    128 sighandler_t Signal(int signum, sighandler_t handler)
    129 {
    130   if (signal(signum, handler)==SIG_ERR)
    131   {
    132     err_sys("signal error");
    133     exit(-1);
    134   }
    135   
    136 }

    4、功能性函数:func.c

     1 #include "unp.h"
     2 
     3 ssize_t writen(int fd, char *buf, size_t n)
     4 {
     5   size_t nleft;
     6   ssize_t nwritten;
     7   char *ptr;
     8   ptr = buf;
     9   nleft = n ;
    10   while(nleft > 0)
    11   {
    12     nwritten = write(fd, ptr, nleft);
    13     if (nwritten < 0 && errno == EINTR)
    14     {
    15       nwritten = 0;
    16     }
    17     else if (nwritten < 0)
    18     {
    19       err_sys("write error");
    20       return -1;
    21     }
    22 
    23     nleft -= nwritten;
    24     ptr += nwritten;
    25   }
    26   return n;
    27 }
    28 
    29 void str_echo(int sockfd)
    30 {
    31   ssize_t n;
    32   char buf[MAXLINE];
    33   again:
    34     while ((n = read(sockfd, buf, MAXLINE))>0)
    35       Writen(sockfd, buf, n);
    36   if (n < 0 && errno == EINTR)
    37   {
    38     goto again;
    39   }
    40   else if (n < 0)
    41   {
    42     err_sys("str_echo error");
    43   }
    44 }
    45 
    46 void sig_chld(int signum)
    47 {
    48     pid_t pid;
    49     int stat;
    50 
    51     while(pid = waitpid(-1, &stat, WNOHANG) >0 )
    52         printf("chlid %d terminated!
    ",pid);
    53     return ;
    54 }

    5、服务器Makefile

     1 serv:serv.o pack.o func.o
     2     gcc serv.o pack.o func.o -o serv
     3 serv.o:serv.c unp.h
     4     gcc -c serv.c -o serv.o
     5 pack.o:pack.c unp.h
     6     gcc -c pack.c -o pack.o
     7 func.o:func.c unp.h
     8     gcc -c func.c -o func.o
     9 .PHONY:clean
    10 clean:
    11     rm -f *.o
  • 相关阅读:
    【洛谷4836】Toy Train 玩具火车(博弈)
    Zabbix Scheduled reports中文乱码
    Openlayers 卷帘地图
    uniapp 使用 uniupgradecenter
    postgresql存储转义字符
    Docker(十一): 安装zookeeper
    Docker(十): 安装Jenkins
    home ftp server使用方法 Dawa
    ImportError: cannot import name 'HTTPClientFactory' from 'twisted.web.client' (unknown location)
    Python 绝对路径与相对路径
  • 原文地址:https://www.cnblogs.com/chenanan/p/7721943.html
Copyright © 2020-2023  润新知