网络安全传输系统

1.传输子系统的设计

a.系统程序框架搭建

客户端:

补充:

fgets()函数用于键盘的读入:fgets(key,n,stdin) 或者 从文件中读入字符串fgets(str,n,fp);

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <netinet/in.h>
  4 #include <sys/socket.h>
  5 #include <sys/stat.h>
  6 #include <errno.h>
  7 #include <unistd.h>
  8 #include <fcntl.h>
  9 #include <string.h>
 10 
 11 #define port 3333
 12  
 13 int  sockclient;
 14 struct sockaddr_in sockaddr1;
 15 char ipaddr[15];
 16 
 17 
 18 int linkS() 
 19 {    
 20     if((sockclient=socket(AF_INET,SOCK_STREAM,0))==-1)
 21     {
 22         perror("socket");    
 23         exit(0);
 24     }
 25         
 26     memset(&sockaddr1,0,sizeof(sockaddr1));
 27     sockaddr1.sin_family = AF_INET;
 28     sockaddr1.sin_addr.s_addr = inet_addr(ipaddr);
 29     sockaddr1.sin_port = htons(port);
 30     
 31     if(connect(sockclient,(struct sockaddr* )&sockaddr1,sizeof(sockaddr1))==-1)
 32     {
 33         perror("connect");
 34         exit(0);
 35     }
 36 
 37     return 1;
 38 }
 39 
 40 //~~~~~~~~~~~~~~~~~~~~~~~上传文件~~~~~~~~~~~~~~~~~~~~~~~~~
 41 void upload_file(char *filename)
 42 {    
 43     int fd;
 44     char buf[1024];
 45     int count=0;
 46     int size = strlen(filename);
 47     char cmd = 'U';
 48 
 49     struct stat fstat;
 50         
 51     if((fd=open(filename,O_RDONLY))==-1)
 52     {
 53         perror("open: ");
 54         return;
 55     }
 56     
 57     /*发送上传命令*/
 58     write(sockclient,&cmd,1);
 59     
 60     /*发送文件名*/
 61     write(sockclient,(void *)&size,4);
 62     write(sockclient,filename,size);
 63     
 64     /*发送文件长度*/
 65     if(stat(filename,&fstat)==-1)
 66         return;
 67     
 68     write(sockclient,(void *)&(fstat.st_size),4);
 69     
 70     /*发送文件内容*/
 71     while((count=read(fd,(void *)buf,1024))>0)
 72     {
 73         write(sockclient,&buf,count);    
 74     }        
 75     
 76     close(fd);
 77 
 78 }
 79 //~~~~~~~~~~~~~~~~~~~~~~~下载文件~~~~~~~~~~~~~~~~~~~~~~~~~
 80 
 81 void download_file(char *filename)
 82 {
 83     int fd;
 84     char buf[1024];
 85     int count=0;
 86     int filesize = 0;
 87     int tmpsize = 0;
 88     int namesize = 0;
 89     char cmd = 'D';
 90     
 91     int size = strlen(filename);
 92     
 93     /*发送下载命令*/
 94     write(sockclient,(void *)&cmd,1);
 95     
 96     /*发送文件名*/
 97     write(sockclient,&size,4);
 98     write(sockclient,filename,size);
 99     
100     /*创建文件*/
101     if((fd=open(filename,O_RDWR|O_CREAT,0777))<0)
102     {
103         perror("open error:\n");    
104     }
105     
106     /*接收文件长度*/
107     read(sockclient,&filesize,4);    
108 
109     while((count=read(sockclient,(void *)buf,1024))>0)
110     {
111         write(fd,&buf,count);
112         tmpsize += count;
113         if(tmpsize==filesize)
114             break;    
115 
116     }
117     
118     close(fd);    
119 }
120 
121 
122 void quit()
123 {
124     char cmd = 'Q';
125     
126     write(sockclient,(void *)&cmd,1);
127     
128     system("clear");
129                 
130     exit(0);    
131 }
132 
133 void menu()
134 {
135     char command;
136     char file_u[30];
137     char file_d[30];
138     char tmp;
139     char c;
140     
141     while(1)
142     {
143         printf("\n------------------------------  1.Upload Files  ------------------------------\n");
144         printf("------------------------------  2.Download Files  ------------------------------\n");
145         printf("------------------------------      3.Exit   ------------------------------------\n");
146         printf("Please input the Client command:");    
147 
148         command=getchar();
149         
150         switch(command)
151         {
152             case '1':
153             {
154                     printf("Upload File:");
155                     
156                     while ((c=getchar()) != '\n' && c != EOF);
157                     
158                     fgets(file_u,30,stdin);
159                     
160                     file_u[strlen(file_u)-1]='\0';
161 
162                     upload_file(file_u);
163               }
164             break;
165                 
166             case '2':
167                 {
168                     printf("Download Files:");
169                     
170                     while ((c=getchar()) != '\n' && c != EOF);
171                     
172                     fgets(file_d,sizeof(file_d),stdin);
173                     
174                     file_d[strlen(file_d)-1]='\0';
175                     
176                     download_file(file_d);
177                   }
178                 break;
179                 
180             case '3':
181                 quit();
182                 
183                 break;
184             
185             default:
186                 printf("Please input right command\n");
187                 break;
188         }
189     }
190 }
191 
192 
193 int main(int argc,char *args[])
194 {
195     if(argc!=2)
196     {
197         printf("format error: you mast enter ipaddr like this : client 192.168.0.6\n");
198         exit(0);
199     }
200     
201     strcpy(ipaddr,args[1]); 
202     
203     linkS();
204     
205     menu();
206     
207     close(sockclient);
208     
209     return 0;
210 }
View Code

服务器:

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <netinet/in.h>
  4 #include <sys/socket.h>
  5 #include <sys/stat.h>
  6 #include <errno.h>
  7 #include <unistd.h>
  8 #include <fcntl.h>
  9 #include <string.h>
 10 
 11 char clientIP[15];                                    /*文件列表*/
 12 int sockfd;                      
 13 int new_fd;
 14 struct sockaddr_in server_addr;
 15 struct sockaddr_in client_addr;
 16 int sin_size,portnumber = 3333;
 17 
 18 
 19 void handle(char cmd)
 20 {
 21     char filename[100];
 22 
 23     int filesize = 0;
 24     int tmpsize = 0;
 25     int namesize = 0;
 26     int count=0;
 27 
 28     int fd;
 29 
 30     
 31     struct stat fstat;
 32     char buf[1024];
 33 
 34     switch(cmd)
 35     {    
 36         case 'U':
 37         {    
 38             
 39             /*接收文件名*/
 40             read(new_fd,&namesize,4);
 41             read(new_fd,(void *)filename,namesize);
 42             filename[namesize]='\0';
 43             
 44             /*创建文件*/
 45             if((fd=open(filename,O_RDWR|O_CREAT,0777))<0)
 46             {
 47                 perror("open error:\n");    
 48             }
 49             
 50             /*接收文件大小*/
 51             read(new_fd,&filesize,4);        
 52 
 53             while((count=read(new_fd,(void *)buf,1024))>0)
 54             {
 55                 write(fd,&buf,count);
 56                 tmpsize += count;
 57                 if(tmpsize==filesize)
 58                     break;    
 59             }
 60             
 61             close(fd);    
 62         }
 63         break;
 64         
 65         case 'D':
 66         {    
 67             /* 接收文件名 */
 68             read(new_fd,&namesize,4);
 69             read(new_fd,filename,namesize);
 70             filename[namesize]='\0';
 71             
 72             if((fd=open(filename,O_RDONLY))==-1)
 73             {
 74                 perror("open: ");
 75                 return;
 76             }
 77             
 78             /*发送文件长度*/
 79             if(stat(filename,&fstat)==-1)
 80                 return;
 81             
 82             write(new_fd,&(fstat.st_size),4);
 83             
 84             /*发送文件内容*/
 85             while((count=read(fd,(void *)buf,1024))>0)
 86             {
 87                 write(new_fd,&buf,count);    
 88             }
 89             
 90             close(fd);
 91 
 92         }
 93         break;
 94     }    
 95 }
 96 
 97 
 98 /*主函数*/
 99 void main()
100 {
101     int i=0;
102     char cmd;
103     
104     if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
105     {
106         perror("socket error");    
107         exit(-1);
108     }
109 
110     bzero(&server_addr,sizeof(struct sockaddr_in));
111     server_addr.sin_family=AF_INET;
112     server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
113     server_addr.sin_port=htons(portnumber);    
114     
115     if(bind(sockfd,(struct sockaddr*)(&server_addr),sizeof(struct sockaddr))<0)
116     {
117         perror("Bind error");
118         exit(1);        
119     }
120     
121     if(listen(sockfd, 5)==-1)
122     {
123         perror("listen error");
124         exit(1);
125     }    
126     
127     
128     while(1)
129     {
130         if((new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size)) == -1)
131         {
132             perror("accept error!");
133             exit(-1);
134         }
135             
136         //strcpy(clientIP,inet_ntoa(client_addr.sin_addr));                 
137         
138         while(1)
139         {
140                 /*读取命令*/
141             read(new_fd,&cmd,1);
142 
143             if(cmd == 'Q')
144             {
145                             close(new_fd);
146                 break;
147             }
148             else
149             {
150                 handle(cmd);
151             }
152         }
153         close(new_fd);        
154     }
155     close(sockfd);
156 }
View Code

 b.加密传输优化

ssl是Secure Sockets Layer(安全套接层协议)的简称,可以提供安全的TCP连接。

将openssl模型移植到arm中,然后在服务器端执行

openssl genrsa -out privkey.pem 2048   (产生私钥)

openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095   (产生带有数字证书的公钥)

(使用openssl 编程模型  另见:http://www.cnblogs.com/chd-zhangbo/p/5516370.html      http://www.cnblogs.com/chd-zhangbo/p/5503614.html   http://blog.chinaunix.net/uid-27717694-id-3530600.html)

 

客户端:

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <netinet/in.h>
  4 #include <sys/socket.h>
  5 #include <sys/stat.h>
  6 #include <errno.h>
  7 #include <unistd.h>
  8 #include <fcntl.h>
  9 #include <string.h>
 10 #include <openssl/ssl.h>
 11 #include <openssl/err.h>
 12 
 13 #define port 3333
 14  
 15 int  sockclient;
 16 struct sockaddr_in sockaddr1;
 17 char ipaddr[15];
 18 
 19 SSL_CTX *ctx;
 20 SSL *ssl;
 21 
 22 
 23 int linkS() 
 24 {    
 25     if((sockclient=socket(AF_INET,SOCK_STREAM,0))==-1)
 26     {
 27         perror("socket");    
 28         exit(0);
 29     }
 30         
 31     memset(&sockaddr1,0,sizeof(sockaddr1));
 32     sockaddr1.sin_family = AF_INET;
 33     sockaddr1.sin_addr.s_addr = inet_addr(ipaddr);
 34     sockaddr1.sin_port = htons(port);
 35     
 36     if(connect(sockclient,(struct sockaddr* )&sockaddr1,sizeof(sockaddr1))==-1)
 37     {
 38         perror("connect");
 39         exit(0);
 40     }
 41     
 42     /*创建SSL*/
 43         ssl = SSL_new(ctx);
 44         SSL_set_fd(ssl, sockclient);
 45         SSL_connect(ssl);
 46 
 47     return 1;
 48 }
 49 
 50 //~~~~~~~~~~~~~~~~~~~~~~~上传文件~~~~~~~~~~~~~~~~~~~~~~~~~
 51 void upload_file(char *filename)
 52 {    
 53     int fd;
 54     char buf[1024];
 55     int count=0;
 56     int size = strlen(filename);
 57     char cmd = 'U';
 58 
 59     struct stat fstat;
 60         
 61     if((fd=open(filename,O_RDONLY))==-1)
 62     {
 63         perror("open: ");
 64         return;
 65     }
 66     
 67     /*发送上传命令*/
 68     //write(sockclient,&cmd,1);
 69     SSL_write(ssl,&cmd,1);
 70     
 71     /*发送文件名*/
 72     //write(sockclient,(void *)&size,4);
 73     //write(sockclient,filename,size);
 74     SSL_write(ssl,(void *)&size,4);
 75     SSL_write(ssl,filename,size);
 76     
 77     /*发送文件长度*/
 78     if(stat(filename,&fstat)==-1)
 79         return;
 80     
 81     //write(sockclient,(void *)&(fstat.st_size),4);
 82     SSL_write(ssl,(void *)&(fstat.st_size),4);
 83     
 84     /*发送文件内容*/
 85     while((count=read(fd,(void *)buf,1024))>0)
 86     {
 87         //write(sockclient,&buf,count);    
 88         SSL_write(ssl,&buf,count);    
 89         
 90     }        
 91     
 92     close(fd);
 93 
 94 }
 95 //~~~~~~~~~~~~~~~~~~~~~~~下载文件~~~~~~~~~~~~~~~~~~~~~~~~~
 96 
 97 void download_file(char *filename)
 98 {
 99     int fd;
100     char buf[1024];
101     int count=0;
102     int filesize = 0;
103     int tmpsize = 0;
104     int namesize = 0;
105     char cmd = 'D';
106     
107     int size = strlen(filename);
108     
109     /*发送下载命令*/
110     //write(sockclient,(void *)&cmd,1);
111     SSL_write(ssl,(void *)&cmd,1);
112     
113     /*发送文件名*/
114     //write(sockclient,&size,4);
115     //write(sockclient,filename,size);
116     SSL_write(ssl,&size,4);
117     SSL_write(ssl,filename,size);
118     
119     /*创建文件*/
120     if((fd=open(filename,O_RDWR|O_CREAT,0777))<0)
121     {
122         perror("open error:\n");    
123     }
124     
125     /*接收文件长度*/
126     //read(sockclient,&filesize,4);    
127     SSL_read(ssl,&filesize,4);    
128 
129     while((count=SSL_read(ssl,(void *)buf,1024))>0)
130     {
131         write(fd,&buf,count);
132         tmpsize += count;
133         if(tmpsize==filesize)
134             break;    
135 
136     }
137     
138     close(fd);    
139 }
140 
141 
142 void quit()
143 {
144     char cmd = 'Q';
145     
146     //write(sockclient,(void *)&cmd,1);
147     SSL_write(ssl,(void *)&cmd,1);
148     
149     system("clear");
150     
151     /*SSL退出*/
152     SSL_shutdown(ssl);
153         SSL_free(ssl);
154         close(sockclient);
155         SSL_CTX_free(ctx);
156                 
157     exit(0);    
158 }
159 
160 void menu()
161 {
162     char command;
163     char file_u[30];
164     char file_d[30];
165     char tmp;
166     char c;
167     
168     while(1)
169     {
170         printf("\n------------------------------  1.Upload Files  ------------------------------\n");
171         printf("------------------------------  2.Download Files  ------------------------------\n");
172         printf("------------------------------      3.Exit   ------------------------------------\n");
173         printf("Please input the Client command:");    
174 
175         command=getchar();
176         
177         switch(command)
178         {
179             case '1':
180             {
181                     printf("Upload File:");
182                     
183                     while ((c=getchar()) != '\n' && c != EOF);
184                     
185                     fgets(file_u,30,stdin);
186                     
187                     file_u[strlen(file_u)-1]='\0';
188 
189                     upload_file(file_u);
190               }
191             break;
192                 
193             case '2':
194                 {
195                     printf("Download Files:");
196                     
197                     while ((c=getchar()) != '\n' && c != EOF);
198                     
199                     fgets(file_d,sizeof(file_d),stdin);
200                     
201                     file_d[strlen(file_d)-1]='\0';
202                     
203                     download_file(file_d);
204                   }
205                 break;
206                 
207             case '3':
208                 quit();
209                 
210                 break;
211             
212             default:
213                 printf("Please input right command\n");
214                 break;
215         }
216     }
217 }
218 
219 
220 int main(int argc,char *args[])
221 {
222     if(argc!=2)
223     {
224         printf("format error: you mast enter ipaddr like this : client 192.168.0.6\n");
225         exit(0);
226     }
227     
228     strcpy(ipaddr,args[1]); 
229     
230     /*SSL库初始化*/
231     SSL_library_init();
232     OpenSSL_add_all_algorithms();
233     SSL_load_error_strings();
234     ctx = SSL_CTX_new(SSLv23_client_method());
235     
236     linkS();
237     
238     menu();
239     
240 
241     
242     return 0;
243 }
View Code

服务器:

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <netinet/in.h>
  4 #include <sys/socket.h>
  5 #include <sys/stat.h>
  6 #include <errno.h>
  7 #include <unistd.h>
  8 #include <fcntl.h>
  9 #include <string.h>
 10 #include <openssl/ssl.h>
 11 #include <openssl/err.h>
 12 
 13 char clientIP[15];                                    /*文件列表*/
 14 int sockfd;                      
 15 int new_fd;
 16 struct sockaddr_in server_addr;
 17 struct sockaddr_in client_addr;
 18 int sin_size,portnumber = 3333;
 19 
 20 
 21 SSL_CTX *ctx;
 22 SSL *ssl;
 23 
 24 
 25 void handle(char cmd)
 26 {
 27     char filename[100];
 28 
 29     int filesize = 0;
 30     int tmpsize = 0;
 31     int namesize = 0;
 32     int count=0;
 33 
 34     int fd;
 35 
 36     
 37     struct stat fstat;
 38     char buf[1024];
 39 
 40     switch(cmd)
 41     {    
 42         case 'U':
 43         {    
 44             
 45             /*接收文件名*/
 46             //read(new_fd,&namesize,4);
 47             //read(new_fd,(void *)filename,namesize);
 48             SSL_read(ssl,&namesize,4);
 49             SSL_read(ssl,(void *)filename,namesize);
 50             filename[namesize]='\0';
 51             
 52             
 53             /*创建文件*/
 54             if((fd=open(filename,O_RDWR|O_CREAT,0777))<0)
 55             {
 56                 perror("open error:\n");    
 57             }
 58             
 59             /*接收文件大小*/
 60             //read(new_fd,&filesize,4);    
 61             SSL_read(ssl,&filesize,4);    
 62 
 63             while((count=SSL_read(ssl,(void *)buf,1024))>0)
 64             {
 65                 write(fd,&buf,count);
 66                 tmpsize += count;
 67                 if(tmpsize==filesize)
 68                     break;    
 69             }
 70             
 71             close(fd);    
 72         }
 73         break;
 74         
 75         case 'D':
 76         {    
 77             /* 接收文件名 */
 78             SSL_read(ssl,&namesize,4);
 79             SSL_read(ssl,filename,namesize);
 80             filename[namesize]='\0';
 81             
 82             if((fd=open(filename,O_RDONLY))==-1)
 83             {
 84                 perror("open: ");
 85                 return;
 86             }
 87             
 88             /*发送文件长度*/
 89             if(stat(filename,&fstat)==-1)
 90                 return;
 91             
 92             SSL_write(ssl,&(fstat.st_size),4);
 93             
 94             /*发送文件内容*/
 95             while((count=read(fd,(void *)buf,1024))>0)
 96             {
 97                 SSL_write(ssl,&buf,count);    
 98             }
 99             
100             close(fd);
101 
102         }
103         break;
104     }    
105 }
106 
107 
108 /*主函数*/
109 void main()
110 {
111     int i=0;
112     char cmd;
113     
114     char pwd[100];
115         char* temp;
116     
117     /*SSL初始化*/
118     SSL_library_init();
119     OpenSSL_add_all_algorithms();
120       SSL_load_error_strings();
121       ctx = SSL_CTX_new(SSLv23_server_method());
122       
123       
124       /* 载入数字证书, 此证书用来发送给客户端。 证书里包含有公钥 */
125       getcwd(pwd,100);
126       if(strlen(pwd)==1)
127             pwd[0]='\0';
128       if (SSL_CTX_use_certificate_file(ctx, temp=strcat(pwd,"/cacert.pem"), SSL_FILETYPE_PEM) <= 0)
129       {
130             ERR_print_errors_fp(stdout);
131             exit(1);
132       }
133       /* 载入用户私钥 */
134       getcwd(pwd,100);
135       if(strlen(pwd)==1)
136             pwd[0]='\0';
137       if (SSL_CTX_use_PrivateKey_file(ctx, temp=strcat(pwd,"/privkey.pem"), SSL_FILETYPE_PEM) <= 0)
138       {
139             ERR_print_errors_fp(stdout);
140             exit(1);
141       }
142   
143       /* 检查用户私钥是否正确 */
144       if (!SSL_CTX_check_private_key(ctx))
145       {
146             ERR_print_errors_fp(stdout);
147             exit(1);
148       }
149     
150     
151     if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
152     {
153         perror("socket error");    
154         exit(-1);
155     }
156 
157     bzero(&server_addr,sizeof(struct sockaddr_in));
158     server_addr.sin_family=AF_INET;
159     server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
160     server_addr.sin_port=htons(portnumber);    
161     
162     if(bind(sockfd,(struct sockaddr*)(&server_addr),sizeof(struct sockaddr))<0)
163     {
164         perror("Bind error");
165         exit(1);        
166     }
167     
168     if(listen(sockfd, 5)==-1)
169     {
170         perror("listen error");
171         exit(1);
172     }    
173     
174     
175     while(1)
176     {
177         if((new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size)) == -1)
178         {
179             perror("accept error!");
180             exit(-1);
181         }
182         
183         /*创建SSL*/    
184                ssl = SSL_new(ctx);
185                SSL_set_fd(ssl, new_fd);
186                if (SSL_accept(ssl) == -1)
187                {
188                   perror("accept");
189                   close(new_fd);
190                }                
191         
192         while(1)
193         {
194                 /*读取命令*/
195             //read(new_fd,&cmd,1);
196             SSL_read(ssl,&cmd,1);
197 
198             if(cmd == 'Q')
199             {
200                             close(new_fd);
201                 break;
202             }
203             else
204             {
205                 handle(cmd);
206             }
207         }
208         
209         /*SSL退出*/
210         SSL_shutdown(ssl);
211             SSL_free(ssl);
212         close(new_fd);        
213     }
214     
215     close(sockfd);
216 }
View Code

 补充:

getcwd()会将当前的工作目录绝对路径复制到参数buf 所指的内存空间,参数size 为buf 的空间大小

2.线程池优化(详解见:http://www.cnblogs.com/chd-zhangbo/p/5516716.html

a.pthread_self()的作用是得到调用线程的ID;

b.条件变量 是  利用线程间共享的全局变量进行同步   的一种机制。主要包括两个动作:一个线程等待   条件变量的成立  而挂起,另一个线程使  条件成立。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起;

c.pthread_cond_wait():传递给这个函数的互斥量对条件进行保护,调用者把锁住的互斥量传给函数,函数然后自动把调用线程放到等待条件的线程列表上,对互斥量进行解锁。,这就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道,这样线程就不会错过条件的任何变化。该函数返回时,互斥量再次被锁住。

d.pthread_mutex_lock()函数说明:当 pthread_mutex_lock() 返回时,该互斥锁已被锁定。调用线程是该互斥锁的属主。如果该互斥锁已被另一个线程锁定和拥有,则调用线程将阻塞,直到该互斥锁变为可用为止。

e.之前一直有个疑问 就是在pthread_creat()函数在执行的时候 要不要等thread_routine函数返回才返回。其实不然pthread_creat函数仅仅返回创建线程是否成功,和这个线程有没有执行thread_routine函数无关。

f.pthread_cond_signal():在调用该函数时,我们说这是给线程或者条件发信号,必须注意:一定要在改变条件状态以后再给线程发信号。

仅仅优化服务器:

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <netinet/in.h>
  4 #include <sys/socket.h>
  5 #include <sys/stat.h>
  6 #include <errno.h>
  7 #include <unistd.h>
  8 #include <fcntl.h>
  9 #include <string.h>
 10 #include <openssl/ssl.h>
 11 #include <openssl/err.h>
 12 #include <pthread.h> 
 13 
 14 char clientIP[15];                                    /*文件列表*/
 15 int sockfd;                      
 16 int new_fd;
 17 struct sockaddr_in server_addr;
 18 struct sockaddr_in client_addr;
 19 int sin_size,portnumber = 3333;
 20 
 21 
 22 SSL_CTX *ctx;
 23 
 24 typedef struct task 
 25 { 
 26     void *(*process) (int arg); 
 27     int arg;
 28     struct task *next; 
 29 } Cthread_task; 
 30 
 31 /*线程池结构*/ 
 32 typedef struct 
 33 { 
 34     pthread_mutex_t queue_lock; 
 35     pthread_cond_t queue_ready; 
 36 
 37     /*链表结构,线程池中所有等待任务*/ 
 38     Cthread_task *queue_head; 
 39 
 40     /*是否销毁线程池*/ 
 41     int shutdown; 
 42     pthread_t *threadid; 
 43     
 44     /*线程池中线程数目*/ 
 45     int max_thread_num; 
 46     
 47     /*当前等待的任务数*/ 
 48     int cur_task_size; 
 49 
 50 } Cthread_pool; 
 51 
 52 Cthread_pool *pool = NULL; 
 53 
 54 void * thread_routine (void *arg) 
 55 { 
 56     printf ("starting thread 0x%x\n", pthread_self ()); 
 57     while (1) 
 58     { 
 59         pthread_mutex_lock (&(pool->queue_lock)); 
 60 
 61         while (pool->cur_task_size == 0 && !pool->shutdown) 
 62         { 
 63             printf ("thread 0x%x is waiting\n", pthread_self ()); 
 64             pthread_cond_wait (&(pool->queue_ready), &(pool->queue_lock)); 
 65         } 
 66 
 67         /*线程池要销毁了*/ 
 68         if (pool->shutdown) 
 69         { 
 70             /*遇到break,continue,return等跳转语句,千万不要忘记先解锁*/ 
 71             pthread_mutex_unlock (&(pool->queue_lock)); 
 72             printf ("thread 0x%x will exit\n", pthread_self ()); 
 73             pthread_exit (NULL); 
 74         } 
 75 
 76         printf ("thread 0x%x is starting to work\n", pthread_self ()); 
 77 
 78          
 79         /*待处理任务减1,并取出链表中的头元素*/ 
 80         pool->cur_task_size--; 
 81         Cthread_task *task = pool->queue_head; 
 82         pool->queue_head = task->next; 
 83         pthread_mutex_unlock (&(pool->queue_lock)); 
 84 
 85         /*调用回调函数,执行任务*/ 
 86         (*(task->process)) (task->arg); 
 87         free (task); 
 88         task = NULL; 
 89     } 
 90     /*这一句应该是不可达的*/ 
 91     pthread_exit (NULL); 
 92 }
 93 
 94 void pool_init (int max_thread_num) 
 95 { 
 96     int i = 0;
 97     
 98     pool = (Cthread_pool *) malloc (sizeof (Cthread_pool)); 
 99 
100     pthread_mutex_init (&(pool->queue_lock), NULL); 
101     /*初始化条件变量*/
102     pthread_cond_init (&(pool->queue_ready), NULL); 
103 
104     pool->queue_head = NULL; 
105 
106     pool->max_thread_num = max_thread_num; 
107     pool->cur_task_size = 0; 
108 
109     pool->shutdown = 0; 
110 
111     pool->threadid = (pthread_t *) malloc (max_thread_num * sizeof (pthread_t)); 
112 
113     for (i = 0; i < max_thread_num; i++) 
114     {  
115         pthread_create (&(pool->threadid[i]), NULL, thread_routine, NULL); 
116     } 
117 } 
118 
119 int pool_add_task (void *(*process) (int arg), int arg) 
120 { 
121     /*构造一个新任务*/ 
122     Cthread_task *task = (Cthread_task *) malloc (sizeof (Cthread_task)); 
123     task->process = process; 
124     task->arg = arg; 
125     task->next = NULL;
126 
127     pthread_mutex_lock (&(pool->queue_lock)); 
128     /*将任务加入到等待队列中*/ 
129     Cthread_task *member = pool->queue_head; 
130     if (member != NULL) 
131     { 
132         while (member->next != NULL) 
133             member = member->next; 
134         member->next = task; 
135     } 
136     else 
137     { 
138         pool->queue_head = task; 
139     } 
140 
141     pool->cur_task_size++; 
142     pthread_mutex_unlock (&(pool->queue_lock)); 
143     
144     pthread_cond_signal (&(pool->queue_ready)); 
145     
146     return 0; 
147 } 
148 
149 void handle(char cmd,SSL *ssl)
150 {
151     char filename[100];
152 
153     int filesize = 0;
154     int tmpsize = 0;
155     int namesize = 0;
156     int count=0;
157 
158     int fd;
159 
160     
161     struct stat fstat;
162     char buf[1024];
163 
164     switch(cmd)
165     {    
166         case 'U':
167         {    
168             
169             /*接收文件名*/
170             //read(new_fd,&namesize,4);
171             //read(new_fd,(void *)filename,namesize);
172             SSL_read(ssl,&namesize,4);
173             SSL_read(ssl,(void *)filename,namesize);
174             filename[namesize]='\0';
175             
176             
177             /*创建文件*/
178             if((fd=open(filename,O_RDWR|O_CREAT,0777))<0)
179             {
180                 perror("open error:\n");    
181             }
182             
183             /*接收文件大小*/
184             //read(new_fd,&filesize,4);    
185             SSL_read(ssl,&filesize,4);    
186 
187             while((count=SSL_read(ssl,(void *)buf,1024))>0)
188             {
189                 write(fd,&buf,count);
190                 tmpsize += count;
191                 if(tmpsize==filesize)
192                     break;    
193             }
194             
195             close(fd);    
196         }
197         break;
198         
199         case 'D':
200         {    
201             /* 接收文件名 */
202             SSL_read(ssl,&namesize,4);
203             SSL_read(ssl,filename,namesize);
204             filename[namesize]='\0';
205             
206             if((fd=open(filename,O_RDONLY))==-1)
207             {
208                 perror("open: ");
209                 return;
210             }
211             
212             /*发送文件长度*/
213             if(stat(filename,&fstat)==-1)
214                 return;
215             
216             SSL_write(ssl,&(fstat.st_size),4);
217             
218             /*发送文件内容*/
219             while((count=read(fd,(void *)buf,1024))>0)
220             {
221                 SSL_write(ssl,&buf,count);    
222             }
223             
224             close(fd);
225 
226         }
227         break;
228     }    
229 }
230 
231 void * process(int arg)
232 {
233     int tmp_fd = arg;
234     SSL *ssl;
235     char cmd;
236     
237     /*创建SSL*/    
238            ssl = SSL_new(ctx);
239            SSL_set_fd(ssl, tmp_fd);
240            if (SSL_accept(ssl) == -1)
241            {
242               perror("accept");
243               close(tmp_fd);
244            }                
245         
246     while(1)
247     {
248         /*读取命令*/
249         //read(new_fd,&cmd,1);
250         SSL_read(ssl,&cmd,1);
251 
252         if(cmd == 'Q')
253         {
254             /*SSL退出*/
255             SSL_shutdown(ssl);
256                 SSL_free(ssl);
257             close(tmp_fd);    
258             break;
259         }
260         else
261         {
262             handle(cmd,ssl);
263         }
264     }
265     
266     return NULL;
267 }
268 
269 
270 /*主函数*/
271 void main()
272 {
273     int i=0;
274 
275     
276     char pwd[100];
277         char* temp;
278     
279     /*SSL初始化*/
280     SSL_library_init();
281     OpenSSL_add_all_algorithms();
282       SSL_load_error_strings();
283       ctx = SSL_CTX_new(SSLv23_server_method());
284       
285       
286       /* 载入数字证书, 此证书用来发送给客户端。 证书里包含有公钥 */
287       getcwd(pwd,100);
288       if(strlen(pwd)==1)
289             pwd[0]='\0';
290       if (SSL_CTX_use_certificate_file(ctx, temp=strcat(pwd,"/cacert.pem"), SSL_FILETYPE_PEM) <= 0)
291       {
292             ERR_print_errors_fp(stdout);
293             exit(1);
294       }
295       /* 载入用户私钥 */
296       getcwd(pwd,100);
297       if(strlen(pwd)==1)
298             pwd[0]='\0';
299       if (SSL_CTX_use_PrivateKey_file(ctx, temp=strcat(pwd,"/privkey.pem"), SSL_FILETYPE_PEM) <= 0)
300       {
301             ERR_print_errors_fp(stdout);
302             exit(1);
303       }
304   
305       /* 检查用户私钥是否正确 */
306       if (!SSL_CTX_check_private_key(ctx))
307       {
308             ERR_print_errors_fp(stdout);
309             exit(1);
310       }
311     
312     
313     if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
314     {
315         perror("socket error");    
316         exit(-1);
317     }
318 
319     bzero(&server_addr,sizeof(struct sockaddr_in));
320     server_addr.sin_family=AF_INET;
321     server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
322     server_addr.sin_port=htons(portnumber);    
323     
324     if(bind(sockfd,(struct sockaddr*)(&server_addr),sizeof(struct sockaddr))<0)
325     {
326         perror("Bind error");
327         exit(1);        
328     }
329     
330     if(listen(sockfd, 5)==-1)
331     {
332         perror("listen error");
333         exit(1);
334     }    
335     
336     //1. 初始化线程池
337     pool_init(5);
338     
339     while(1)
340     {
341         if((new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size)) == -1)
342         {
343             perror("accept error!");
344             exit(-1);
345         }
346         
347             //2. 执行process,将process任务交给线程池
348             pool_add_task(process,new_fd);
349             
350     }
351     
352     close(sockfd);
353 }
View Code

3.账号管理子系统设计(详解见:http://www.cnblogs.com/chd-zhangbo/p/5516934.html

sqlite3从功能上来说,这是一个数据库系统,其本质上是由一套用C语言实现的对数据库文件的读写接口。此类接口支持sql语言。所以,这不需要什么服务器,也没有数据库权限管理。在程序中可以随时调用API创建一个数据库文件,进行数据存储,非常灵活易用。

sqlite3_exec:这就是执行一条sql 语句的函数

回调函数的第一个参数是sqlite3_exec函数里面的倒数第二个参数传进来的。第二个参数是执行sqlite3_exec里面的sql语句满足条件的记录数,第三个参数是具体对应记录里查到的内容

第四个参数和第三个参数一一对应,表示第三个字段的名称。   

对于该项目来说 回调函数的参数:1.传进来的为NULL  2.argc  3.argv (代表最后输入的内容:最后输入的就是密码,倒数第二个代表用户名) 4.对应最后输入的内容的名称

仅仅对客户端进行设计:

#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#include <sqlite3.h> 

#define port 3333
 
int  sockclient;
struct sockaddr_in sockaddr1;
char ipaddr[15];

SSL_CTX *ctx;
SSL *ssl;


int linkS() 
{    
    if((sockclient=socket(AF_INET,SOCK_STREAM,0))==-1)
    {
        perror("socket");    
        exit(0);
    }
        
    memset(&sockaddr1,0,sizeof(sockaddr1));
    sockaddr1.sin_family = AF_INET;
    sockaddr1.sin_addr.s_addr = inet_addr(ipaddr);
    sockaddr1.sin_port = htons(port);
    
    if(connect(sockclient,(struct sockaddr* )&sockaddr1,sizeof(sockaddr1))==-1)
    {
        perror("connect");
        exit(0);
    }
    
    /*创建SSL*/
        ssl = SSL_new(ctx);
        SSL_set_fd(ssl, sockclient);
        SSL_connect(ssl);

    return 1;
}

//~~~~~~~~~~~~~~~~~~~~~~~上传文件~~~~~~~~~~~~~~~~~~~~~~~~~
void upload_file(char *filename)
{    
    int fd;
    char buf[1024];
    int count=0;
    int size = strlen(filename);
    char cmd = 'U';

    struct stat fstat;
        
    if((fd=open(filename,O_RDONLY))==-1)
    {
        perror("open: ");
        return;
    }
    
    /*发送上传命令*/
    //write(sockclient,&cmd,1);
    SSL_write(ssl,&cmd,1);
    
    /*发送文件名*/
    //write(sockclient,(void *)&size,4);
    //write(sockclient,filename,size);
    SSL_write(ssl,(void *)&size,4);
    SSL_write(ssl,filename,size);
    
    /*发送文件长度*/
    if(stat(filename,&fstat)==-1)
        return;
    
    //write(sockclient,(void *)&(fstat.st_size),4);
    SSL_write(ssl,(void *)&(fstat.st_size),4);
    
    /*发送文件内容*/
    while((count=read(fd,(void *)buf,1024))>0)
    {
        //write(sockclient,&buf,count);    
        SSL_write(ssl,&buf,count);    
        
    }        
    
    close(fd);

}
//~~~~~~~~~~~~~~~~~~~~~~~下载文件~~~~~~~~~~~~~~~~~~~~~~~~~

void download_file(char *filename)
{
    int fd;
    char buf[1024];
    int count=0;
    int filesize = 0;
    int tmpsize = 0;
    int namesize = 0;
    char cmd = 'D';
    
    int size = strlen(filename);
    
    /*发送下载命令*/
    //write(sockclient,(void *)&cmd,1);
    SSL_write(ssl,(void *)&cmd,1);
    
    /*发送文件名*/
    //write(sockclient,&size,4);
    //write(sockclient,filename,size);
    SSL_write(ssl,&size,4);
    SSL_write(ssl,filename,size);
    
    /*创建文件*/
    if((fd=open(filename,O_RDWR|O_CREAT,0777))<0)
    {
        perror("open error:\n");    
    }
    
    /*接收文件长度*/
    //read(sockclient,&filesize,4);    
    SSL_read(ssl,&filesize,4);    

    while((count=SSL_read(ssl,(void *)buf,1024))>0)
    {
        write(fd,&buf,count);
        tmpsize += count;
        if(tmpsize==filesize)
            break;    

    }
    
    close(fd);    
}


void quit()
{
    char cmd = 'Q';
    
    //write(sockclient,(void *)&cmd,1);
    SSL_write(ssl,(void *)&cmd,1);
    
    system("clear");
    
    /*SSL退出*/
    SSL_shutdown(ssl);
        SSL_free(ssl);
        close(sockclient);
        SSL_CTX_free(ctx);
                
    exit(0);    
}

void menu()
{
    char command;
    char file_u[30];
    char file_d[30];
    char tmp;
    char c;
    
    while(1)
    {
        printf("\n------------------------------  1.Upload Files  ------------------------------\n");
        printf("------------------------------  2.Download Files  ------------------------------\n");
        printf("------------------------------      3.Exit   ------------------------------------\n");
        printf("Please input the Client command:");    

        while ((c=getchar()) != '\n' && c != EOF);
        command=getchar();
        
        switch(command)
        {
            case '1':
            {
                    printf("Upload File:");
                    
                    while ((c=getchar()) != '\n' && c != EOF);
                    
                    fgets(file_u,30,stdin);
                    
                    file_u[strlen(file_u)-1]='\0';

                    upload_file(file_u);
              }
            break;
                
            case '2':
                {
                    printf("Download Files:");
                    
                    while ((c=getchar()) != '\n' && c != EOF);
                    
                    fgets(file_d,sizeof(file_d),stdin);
                    
                    file_d[strlen(file_d)-1]='\0';
                    
                    download_file(file_d);
                  }
                break;
                
            case '3':
                quit();
                
                break;
            
            default:
                printf("Please input right command\n");
                break;
        }
    }
}

char passwd_d[10];

static int callback(void *NotUsed, int argc, char **argv, char **azColName) 
{ 
      int i; 
     for(i=0; i<argc; i++) 
     { 
         //printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); 
         strcpy(passwd_d,argv[i]);
     } 
     printf("\n"); 
    return 0;

} 

int login()
{
     char username[10];
     char passwd[10];
     sqlite3 *db;
     char sql[50];
     
     int success;
     
     //1. 通知用户输入用户名和密码
     printf("User name: ");
     scanf("%s",username);
     
     printf("Password: ");
     scanf("%s",passwd);
     
     
     //2. 根据用户名,从数据库提取正确的密码
     
     sprintf(sql, "select passwd from tb0 where name='%s';",username); 
     
     sqlite3_open("user.db", &db); 
     
     sqlite3_exec(db, sql, callback, 0, NULL);
     
     sqlite3_close(db); 
     
     
     //3. 比较用户输入的密码和数据库提取出的密码,以决定是否登录成功
     
     success = strcmp(passwd,passwd_d);
         
     return success;    
}

int main(int argc,char *args[])
{
    if(argc!=2)
    {
        printf("format error: you mast enter ipaddr like this : client 192.168.0.6\n");
        exit(0);
    }
    
    strcpy(ipaddr,args[1]); 
    
    if (login()!=0)
    {
         printf("wrong username or password!\n");
         exit(0);    
    }
    
    
    /*SSL库初始化*/
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    ctx = SSL_CTX_new(SSLv23_client_method());
    
    linkS();
    
    menu();
    
    return 0;
}
View Code
 
运行此项目:
服务器端:
./server
客户端:
首先在客户端上 建立数据库的表
./test_db user.db "create table tb0(name varchar(10),passwd vachar(10))"
./test.db user.db "insert into the values('david,123')"
 
然后在客户端上执行./client 192.168.1.1
username:david
password:123
分别将用户名和密码输入即可登录服务器
posted @ 2016-12-27 19:57  china_sdd  阅读(381)  评论(0编辑  收藏  举报