网络安全传输系统
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 }
服务器:
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 }
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 }
服务器:
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 }
补充:
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 }
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; }