• 网络安全传输系统


    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:
    ");    
    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("
    ------------------------------  1.Upload Files  ------------------------------
    ");
    144         printf("------------------------------  2.Download Files  ------------------------------
    ");
    145         printf("------------------------------      3.Exit   ------------------------------------
    ");
    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()) != '
    ' && c != EOF);
    157                     
    158                     fgets(file_u,30,stdin);
    159                     
    160                     file_u[strlen(file_u)-1]='';
    161 
    162                     upload_file(file_u);
    163               }
    164             break;
    165                 
    166             case '2':
    167                 {
    168                     printf("Download Files:");
    169                     
    170                     while ((c=getchar()) != '
    ' && c != EOF);
    171                     
    172                     fgets(file_d,sizeof(file_d),stdin);
    173                     
    174                     file_d[strlen(file_d)-1]='';
    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
    ");
    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
    ");
    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]='';
     43             
     44             /*创建文件*/
     45             if((fd=open(filename,O_RDWR|O_CREAT,0777))<0)
     46             {
     47                 perror("open error:
    ");    
     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]='';
     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:
    ");    
    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("
    ------------------------------  1.Upload Files  ------------------------------
    ");
    171         printf("------------------------------  2.Download Files  ------------------------------
    ");
    172         printf("------------------------------      3.Exit   ------------------------------------
    ");
    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()) != '
    ' && c != EOF);
    184                     
    185                     fgets(file_u,30,stdin);
    186                     
    187                     file_u[strlen(file_u)-1]='';
    188 
    189                     upload_file(file_u);
    190               }
    191             break;
    192                 
    193             case '2':
    194                 {
    195                     printf("Download Files:");
    196                     
    197                     while ((c=getchar()) != '
    ' && c != EOF);
    198                     
    199                     fgets(file_d,sizeof(file_d),stdin);
    200                     
    201                     file_d[strlen(file_d)-1]='';
    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
    ");
    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
    ");
    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]='';
     51             
     52             
     53             /*创建文件*/
     54             if((fd=open(filename,O_RDWR|O_CREAT,0777))<0)
     55             {
     56                 perror("open error:
    ");    
     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]='';
     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]='';
    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]='';
    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
    ", 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
    ", 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
    ", pthread_self ()); 
     73             pthread_exit (NULL); 
     74         } 
     75 
     76         printf ("thread 0x%x is starting to work
    ", 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]='';
    175             
    176             
    177             /*创建文件*/
    178             if((fd=open(filename,O_RDWR|O_CREAT,0777))<0)
    179             {
    180                 perror("open error:
    ");    
    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]='';
    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]='';
    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]='';
    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:
    ");    
        }
        
        /*接收文件长度*/
        //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("
    ------------------------------  1.Upload Files  ------------------------------
    ");
            printf("------------------------------  2.Download Files  ------------------------------
    ");
            printf("------------------------------      3.Exit   ------------------------------------
    ");
            printf("Please input the Client command:");    
    
            while ((c=getchar()) != '
    ' && c != EOF);
            command=getchar();
            
            switch(command)
            {
                case '1':
                {
                        printf("Upload File:");
                        
                        while ((c=getchar()) != '
    ' && c != EOF);
                        
                        fgets(file_u,30,stdin);
                        
                        file_u[strlen(file_u)-1]='';
    
                        upload_file(file_u);
                  }
                break;
                    
                case '2':
                    {
                        printf("Download Files:");
                        
                        while ((c=getchar()) != '
    ' && c != EOF);
                        
                        fgets(file_d,sizeof(file_d),stdin);
                        
                        file_d[strlen(file_d)-1]='';
                        
                        download_file(file_d);
                      }
                    break;
                    
                case '3':
                    quit();
                    
                    break;
                
                default:
                    printf("Please input right command
    ");
                    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
    ", azColName[i], argv[i] ? argv[i] : "NULL"); 
             strcpy(passwd_d,argv[i]);
         } 
         printf("
    "); 
        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
    ");
            exit(0);
        }
        
        strcpy(ipaddr,args[1]); 
        
        if (login()!=0)
        {
             printf("wrong username or password!
    ");
             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
    分别将用户名和密码输入即可登录服务器
  • 相关阅读:
    已知自然数A、B不互质,A、B最大公约数和最小公倍数之和为35,那么A+B的最小值是多少?
    mysql null字段 空字段 查询效率
    sql注入和网站攻击思路
    软件服务新时代:开源软件的盈利模式
    eclipse maven插件配置,jdk全局版本调整
    spring事务(isolation隔离级别,propagation事务传播属性)
    GBDT 算法
    博客园的 “随笔、文章、新闻、日记”有啥区别
    1.3 Java中的标识符和关键字
    1.1 Java 的概述
  • 原文地址:https://www.cnblogs.com/china-sdd/p/6227331.html
Copyright © 2020-2023  润新知