今天實現的這個伺服器程式加入了對多個客戶端同時請求處理的實現,伺服器端通過對每次監聽到的客戶端程式新建一個子進程,進行相關的處理,將從客戶端傳來的字元串數據,轉化為大寫的字元串序列,然重新寫回到connfd;另一方面,客戶端通過在標準輸入里獲取客戶輸入到的字元串序列,傳送到connfd,再從conn ...
今天實現的這個伺服器程式加入了對多個客戶端同時請求處理的實現,伺服器端通過對每次監聽到的客戶端程式新建一個子進程,進行相關的處理,將從客戶端傳來的字元串數據,轉化為大寫的字元串序列,然重新寫回到connfd;另一方面,客戶端通過在標準輸入里獲取客戶輸入到的字元串序列,傳送到connfd,再從connfd讀取經伺服器處理過的字元串序列列印到標準輸出上。
同時,加上了對某些socket原語函數的封裝處理,主要封裝了對出錯的處理機制,基本原語函數都以相應大寫首個字元的命名錶示,定義在“wrap.c”和“wrap.h”文件中。
wrap.h
1 /* wrap.h */ 2 #ifndef __WRAP_H_ 3 #define __WRAP_H_ 4 5 void perr_exit(const char *s); 6 int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr); 7 void Bind(int fd, const struct sockaddr *sa, socklen_t salen); 8 void Connect(int fd, const struct sockaddr *sa, socklen_t salen); 9 void Listen(int fd, int backlog); 10 int Socket(int family, int type, int protocol); 11 ssize_t Read(int fd, void *ptr, size_t nbytes); 12 ssize_t Write(int fd, const void *ptr, size_t nbytes); 13 void Close(int fd); 14 ssize_t Readn(int fd, void *vptr, size_t n); 15 ssize_t Writen(int fd, const void *vptr, size_t n); 16 static ssize_t my_read(int fd, char *ptr); 17 ssize_t Readline(int fd, void *vptr, size_t maxlen); 18 19 #endif
wrap.c
1 /*wrap.c */ 2 #include<stdlib.h> 3 #include<errno.h> 4 #include<sys/socket.h> 5 6 void perr_exit(const char* s) 7 { 8 perror(s); 9 exit(1); 10 } 11 12 int Accept(int fd,struct sockaddr *sa,socklen_t *salenptr) 13 { 14 int n; 15 again: 16 if((n=accept(fd,sa,salenptr))<0){ 17 if((errno==ECONNABORTED)||(errno==EINTR)) 18 goto again; 19 else 20 perr_exit("accept error"); 21 } 22 return n; 23 } 24 25 void Bind(int fd,const struct sockaddr *sa,socklen_t salen) 26 { 27 if(bind(fd,sa,salen)<0) 28 perr_exit("bind error"); 29 } 30 31 void Connect(int fd,const struct sockaddr *sa,socklen_t salen) 32 { 33 if(connect(fd,sa,salen)<0) 34 perr_exit("connect error"); 35 } 36 37 void Listen(int fd,int backlog) 38 { 39 if(listen(fd,backlog)<0) 40 perr_exit("listen error"); 41 } 42 43 int Socket(int family,int type,int protocol) 44 { 45 int n; 46 if((n=socket(family,type,protocol))<0) 47 perr_exit("socket error"); 48 return n; 49 } 50 51 ssize_t Read(int fd,void *ptr,size_t nbytes) 52 { 53 ssize_t n; 54 again: 55 if((n=read(fd,ptr,nbytes))==-1){ 56 if(errno==EINTR) 57 goto again; 58 else 59 return -1; 60 } 61 return n; 62 } 63 64 ssize_t Write(int fd,const void *ptr,size_t nbytes) 65 { 66 ssize_t n; 67 again: 68 if((n=write(fd,ptr,nbytes))==-1){ 69 if(errno==EINTR) 70 goto again; 71 else 72 return -1; 73 } 74 return n; 75 } 76 77 void Close(int fd) 78 { 79 if(close(fd)==-1) 80 perr_exit("close error"); 81 } 82 83 ssize_t Readn(int fd,void *vptr,ssize_t n) 84 { 85 size_t nleft; 86 ssize_t nread; 87 char *ptr; 88 ptr=vptr; 89 nleft=n; 90 while(nleft>0){ 91 if((nread=read(fd,ptr,nleft))<0){ 92 if(errno==EINTR) 93 nread=0; 94 else 95 return -1; 96 }else if(nread==0) 97 break; 98 nleft-=nread; 99 ptr+=nread; 100 } 101 return n-nleft; 102 } 103 104 105 ssize_t Writen(int fd,const void *vptr,size_t n) 106 { 107 size_t nleft; 108 ssize_t nwritten; 109 const char* ptr; 110 ptr=vptr; 111 nleft=n; 112 while(nleft>0){ 113 if(nwritten=write(fd,ptr,nleft)<=0){ 114 if(nwritten<0&&errno==EINTR) 115 nwritten=0; 116 else 117 return -1; 118 } 119 nleft-=nwritten; 120 ptr+=nwritten; 121 } 122 return n; 123 } 124 125 static ssize_t my_read(int fd,char* ptr) 126 { 127 static int read_cnt; 128 static char *read_ptr; 129 static char read_buf[100]; 130 if(read_cnt<=0){ 131 again: 132 if((read_cnt=read(fd,read_buf,sizeof(read_buf)))<0){ 133 if(errno==EINTR) 134 goto again; 135 else 136 return -1; 137 }else if(read_cnt==0) 138 return 0; 139 read_ptr=read_buf; 140 } 141 read_cnt--; 142 *ptr=*read_ptr++; 143 return 1; 144 } 145 146 ssize_t Readline(int fd,void *vptr,size_t maxlen) 147 { 148 ssize_t n,rc; 149 char c,*ptr; 150 ptr=vptr; 151 for(n=1;n<maxlen;n++){ 152 if((rc=my_read(fd,&c))==1){ 153 *ptr++=c; 154 if(c=='\n') 155 break; 156 }else if(rc==0){ 157 *ptr=0; 158 return n-1; 159 }else 160 return -1; 161 } 162 *ptr=0; 163 return n; 164 } 165
伺服器端:
1 #include<stdlib.h> 2 #include<stdio.h> 3 #include<unistd.h> 4 #include<string.h> 5 #include<netinet/in.h> 6 #include<sys/types.h> 7 #include<sys/socket.h> 8 #include<arpa/inet.h> 9 #include "wrap.c" 10 #define SERVER_PORT 8000 11 #define BUFSIZE 80 12 int main(int argc,char* argv[]) 13 { 14 struct sockaddr_in serveraddr,clientaddr; 15 int listenfd,connfd,len,clientaddr_len,i; 16 char buf[BUFSIZE]; 17 char str[BUFSIZE]; 18 pid_t pid; 19 listenfd=Socket(AF_INET,SOCK_STREAM,0); 20 21 bzero(&serveraddr,sizeof(serveraddr)); 22 serveraddr.sin_family=AF_INET; 23 serveraddr.sin_addr.s_addr=htonl(INADDR_ANY); 24 serveraddr.sin_port=htons(SERVER_PORT); 25 26 Bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)); 27 28 Listen(listenfd,128); 29 printf("waiting for connecting\n"); 30 while(1){ 31 clientaddr_len=sizeof(clientaddr); 32 connfd=Accept(listenfd,(struct sockaddr *)&clientaddr,&clientaddr_len); 33 printf("client ip: %s\tport :%d\n",inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,str,sizeof(str)),ntohs(clientaddr.sin_port)); 34 pid=fork(); 35 if(pid==0){ 36 Close(listenfd); 37 while(1){ 38 len=Read(connfd,buf,sizeof(buf)); 39 for(i=0;i<len;i++) 40 buf[i]=toupper(buf[i]); 41 Write(connfd,buf,len); 42 } 43 Close(connfd); 44 return 0; 45 }else if(pid>0){ 46 Close(connfd); 47 } 48 else{ 49 //error deal 50 } 51 } 52 // Close(listenfd); 53 return 0; 54 }
客戶端:
1 #include<stdlib.h> 2 #include<stdio.h> 3 #include<string.h> 4 #include<sys/types.h> 5 #include<netinet/in.h> 6 #include<sys/socket.h> 7 #include<unistd.h> 8 #include "wrap.c" 9 #define SERVER_PORT 8000 10 #define BUFSIZE 80 11 int main(int argc,char* argv[]) 12 { 13 int confd,len; 14 struct sockaddr_in serveraddr; 15 confd=Socket(AF_INET,SOCK_STREAM,0); 16 char buf[BUFSIZE]; 17 18 bzero(&serveraddr,sizeof(serveraddr)); 19 serveraddr.sin_family=AF_INET; 20 inet_pton(AF_INET,"127.0.0.1",&serveraddr.sin_addr.s_addr); 21 serveraddr.sin_port=htons(SERVER_PORT); 22 23 Connect(confd,(struct sockaddr*)&serveraddr,sizeof(serveraddr)); 24 while(fgets(buf,sizeof(buf),stdin)){ 25 Write(confd,buf,strlen(buf)); 26 len=Read(confd,buf,BUFSIZE); 27 printf("the result from server:\n"); 28 Write(STDOUT_FILENO,buf,len); 29 } 30 31 Close(confd); 32 return 0; 33 }