分析过程
代码实现.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 }