多进程并发服务器简单实现

分析过程

在这里插入图片描述代码实现.server
注意:wrap是自己封装网络编程的常用错误处理,避免主函数中太多判断逻辑不清;

  1 #include"wrap.h"
  2 #define SERV_PORT 8888
  3 
  4 #include<sys/types.h>
  5 #include<sys/wait.h>
  6 void waitChild(int sig)
  7 {   
  8     int pid = waitpid(-1,NULL,WNOHANG);
  9     printf("pid = %d is waited\n",pid);
 10 }
 11 int main()
 12 {
 13     int lfd,cfd;
 14     int pid;
 15     struct sockaddr_in saddr,caddr;
 16     lfd = Socket(AF_INET,SOCK_STREAM,0);
 17 
 18     saddr.sin_family = AF_INET;
 19     saddr.sin_port = htons(SERV_PORT);
 20     inet_pton(AF_INET,"127.0.0.1",&saddr.sin_addr.s_addr);
 21     Bind(lfd,(struct sockaddr*)&saddr,sizeof(saddr));
 22 
 23     Listen(lfd,128);
 24     while(1)
 25     {
 26         socklen_t caddr_len = sizeof(caddr);
 27         cfd =  Accept(lfd,(struct sockaddr*)&caddr, &caddr_len);
 28 
 29         char buf[BUFSIZ];
 30         printf("client ip = %s , port =%d\n",inet_ntop(AF_INET,&caddr.sin_addr.s_addr,buf,sizeof(buf))
 31                     ,ntohs(caddr.sin_port));
 32 
 33         pid = fork();
 34         if(pid < 0 )
 35         {
 36             perror("fork error");
 37             exit(1);
 38         }
 39         else if(pid >0)//父进程
 40         {
 41             Close(cfd);
 42             signal(SIGCHLD,waitChild);
 43         }
 44         else  //子进程,操作退出循环做
 45         {
 46             Close(lfd);
 47             break;
 48         }
 49     }
 50     int n=0,i;
 51     char buf[BUFSIZ];
 52     if(pid ==0 )
 53     {
 54         while(1)
 55         {
 56             n=Read(cfd,buf,sizeof(buf));//自己封装Read只是派排除了信号的中断情况
 57             if( n==-1)
 58               perror("read error");
 59             else if(n==0)
 60             {
 61                 Close(cfd);
 62                 break;
 63             }
 64             else
 65             {
 66                 for(i=0; i<n;i++)
 67                   buf[i]=toupper(buf[i]);
 68             }
 69             Write(cfd,buf,n);
 70         }
 71     }
 72 
 73     return 0;
 74 }

**

执行与客户端连接结果

**

yan@ubuntu:~/net/2$ ./Server
client ip = 127.0.0.1 , port =60610
client ip = 127.0.0.1 , port =60612
client ip = 127.0.0.1 , port=60614

wrap.h

  1 #pragma once 
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 #include<unistd.h>
  6 #include<sys/types.h>
  7 #include<sys/socket.h>
  8 #include<ctype.h>
  9 #include<netinet/in.h>
 10 #include<arpa/inet.h>
 11 #include<errno.h>
 12 
 13 void perr_exit(const char * s);
 14 int Socket( int family , int type , int protocol);
 15 
 16 int Bind( int fd , const struct sockaddr *sa , socklen_t salen);
 17 
 18 int Listen( int fd , int backlog );
 19 
 20 int Accept( int fd , struct sockaddr *sa , socklen_t *salenptr );
 21 
 22 int Close( int fd );
 23 
 24 int Connect( int fd , const struct sockaddr *sa , socklen_t salen);
 25 ssize_t Read( int fd, void *ptr, size_t nbytes);
 26 ssize_t Write( int fd, const void *ptr, size_t nbytes);
 27 
 28 /*参数三 : 应该(指定)读的字节数*/
 29 ssize_t Readn( int fd,  void *vptr, size_t n);
 30 ssize_t Writen( int fd, const void *vptr, size_t n);
 31 
 32 static ssize_t my_read( int fd, char *ptr);
 33 ssize_t Readline (int fd, void *vptr, size_t maxlen);

wrap.c

  1 #include "wrap.h"
  2 
  3 void perr_exit(const char * s)
  4 {
  5     perror(s);
  6     exit(-1);
  7 }
  8 
  9 int Socket( int family , int type , int protocol)
 10 {
 11     int n;
 12     if(( n = socket(family , type , protocol))< 0)
 13       perr_exit("socket error");
 14 }
 15 
 16 int Bind( int fd , const struct sockaddr *sa , socklen_t salen)
 17 {
 18     int n;
 19     if((n = bind( fd , sa, salen)) < 0)
 20         perr_exit("bind error");
 21     return n;
 22 }
 23 
 24 int Listen( int fd , int backlog )
 25 {
 26     int n;
 27     if(( n = listen(fd, backlog)) < 0 )
 28       perr_exit("listen error");
 29     return n;
 30 }
 31 
 32 int Accept( int fd , struct sockaddr *sa , socklen_t *salenptr )
 33 {
 34     int n;
 35 again:
 36     if((n = accept(fd,sa,salenptr)) < 0 )//连接异常断开,信号中断
 37     {
 38         if((errno == ECONNABORTED) || (errno == EINTR))
 39             goto again;
 40         else
 41           perr_exit("accept error");
 42     }
 43     return n;
 44 }
 45 
 46 int Close( int fd )
 47 {
 48     int n;
 49     if(( n = close(fd)) < 0)
 50       perr_exit("close error");
 51     return n;
 52 }
 53 
 54 int Connect( int fd , const struct sockaddr *sa , socklen_t salen)
 55 {
 56     int n;
 57     if(( n = connect( fd, sa, salen)) < 0 )
 58       perr_exit("connect error");
 59     return n;
 60 }
 61 ssize_t Read( int fd, void *ptr, size_t nbytes)
 62 {
 63     ssize_t n;
 64 
 65 again:
 66     if((n = read(fd , ptr , nbytes)) < 0)
 67       if(errno == EINTR)//被信号中断,重新读
 68         goto again;
 69       else
 70         return -1;
 71     else
 72       return n;
 73 }
 74 ssize_t Write( int fd, const void *ptr, size_t nbytes)
 75 {
 76     ssize_t n;
 77 
 78 again:
 79     if(( n = write(fd, ptr, nbytes)) < 0)
 80       if(errno == EINTR)
 81           goto again;
 82       else
 83         return -1;
 84     return n;
 85 }
 86 
 87 /*参数三 : 应该(指定)读的字节数*/
 89 {
 90     size_t nleft = n;//unsignied int 剩余未读取的字节数
 91     char * ptr = vptr;
 92     ssize_t nread; //实际读到的字节数
 93     
 94     while( nleft > 0)
 95     {
 96         if((nread = read(fd, ptr, nleft)) < 0)
 97         {
 98             if(errno == EINTR)
 99               nread = 0;
100             else 
101               return -1;
102         }     
103         else if(nread == 0)
104           break;
105           
106         nleft -=nread;
107         ptr +=nread;
108         
109         return n-nleft;  //返回总共读了多少字节;
110     }   
111 }   
112 ssize_t Writen( int fd, const void *vptr, size_t n)
113 {
114     size_t nleft = n;//剩余写的数量
115     const char * ptr = vptr;
116     ssize_t nwritten;//已经写进去的数量
117 
118     while( nleft > 0 )
119     {
120         if((nwritten = write(fd, vptr , nleft)) <= 0)
121           if(nwritten < 0 && errno ==EINTR)
122             nwritten = 0;
123           else
124             return -1;
125 
126         nleft -= nwritten;
127         ptr +=nwritten;
128     }
129     return n;
130 }
131 
133 {
134     static int read_cnt;
135     static char *read_ptr;
136     static char read_buf[100];
137     
138     if(read_cnt <=0)
139     {
140 again:
141         if((read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0)
142         {
143             if(errno == EINTR)
144               goto again;
145             return -1;
146         }   
147         else if(read_cnt == 0)
148             return 0;
149             
150         read_ptr = read_buf;
151     }   
152     read_cnt--;
153     *ptr = *read_ptr++;
154     return 1;
155 }   
156 /*readline(文件描述符) 代替 fgets(FILE *)*/
157 //vptr传出参数
158 ssize_t Readline (int fd, void *vptr, size_t maxlen)
159 {
160     ssize_t n,rc;
161     char c,*ptr;
162     ptr = vptr;
163 
164     for(n =1 ; n < maxlen ; ++n)
165     {
166         if((rc = my_read(fd,&c)) == 1) //调用成功返回1
167         {
168             *ptr++ = c;
169             if(c == '\n')
170               break;
171         }
172         else if(rc == 0)
173         {
174             *ptr = 0;
175             return n-1;
176         }
177         else
178           return -1;
179     }
180     *ptr = 0;
181 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YanWenCheng_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值