学习 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
原文地址:https://www.cnblogs.com/chenanan/p/7721943.html