2-1. 基于OpenSSL的传输子系统实现

一. 基本传输子系统程序设计

  客户端可上传文件至服务器,或下载服务器上的文件

  系统程序构架:

客户端 服务器

TCP建立连接

menu()-> 上传命令、下载命令

close(socket)

TCP建立连接

handle()-> 根据命令响应

close(socket);

 

 

 

 

 

 

主函数框架:

客户端 服务器
int main(int argc, char *args[])
{
    if (argc != 2)
    {
        printf("usage:./client 192.168.10.18(serverip)");
        exit(0);    //退出    
    }
    strcpy(ipaddr,args[1]);  //将服务器地址放入字符串中
    //1.建立连接
    clink();  
    //2.输入命令, 实现上传和下载,实现菜单
    menu();
    //3.关闭连接
    close(sockfd); 
    return 0;
}
 
int clink()
{
    //1.创建socket
    sockfd = socket(AF_INET, SOCK_STREAM, 0);//IPv4
    
    /*2.1 初始化地址*/
    memset(&sockaddr1,0,sizeof(sockaddr1));//清零
    sockaddr1.sin_family = AF_INET;//协议族
    sockaddr1.sin_addr.s_addr = inet_addr(ipaddr);//
    sockaddr1.sin_port = htons(port);//端口,跟随网络传输,
    //2.连接服务器    
    connect(sockfd,(struct sockaddr *)&sockaddr1,
sizeof(sockaddr1)); return 1; }

 

int main()
{
    //1.1创建socket
    sockfd = socket(AF_INET, SOCK_STREAM, 0);  //IPv4,用于TCP通信
    //1.2绑定地址
     /*初始化地址*/
    bzero(&server_addr,sizeof(struct sockaddr_in));//清零
    server_addr.sin_family = AF_INET;//协议族
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//跟随网络传输 
    server_addr.sin_port = htons(port);//端口,跟随网络传输
     /*绑定地址*/  
   //1.3监听端口
bind(sockfd,(struct sockaddr *)(&server_addr),
                sizeof(struct sockaddr)); listen(sockfd,5); //客户机数目 //1.4等待连接 while(1) { //client_addr保存客户机地址 &sin_size长度的地址 new_fd = accept(sockfd,(struct sockaddr *)
                    (&client_addr),&sin_size);
//2.响应客户端请求 while(1) { read(new_fd,&cmd,1); //读取操作类型码 if(cmd == 'Q') { close(new_fd); break; } else { handle(cmd); } } close(sockfd); } return 0; }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

---------------------------------------------------------------------------------------

  客户端操作菜单及服务器端命令响应:

客户端操作菜单 服务器端命令响应
 1 void menu()
 2 {
 3     while(1)
 4     {
 5         printf("\n-------- 1. Upload Files -----------\n");    
 6         printf("-------- 2. Download Files ----------\n");    
 7         printf("--------------- 3. Exit ------------\n");
 8         printf("Please input the Client command:");      
 9         command = getchar();    //等待用户输入字符
10         switch(command)
11         {
12 case '1':
13   {          //上传文件
14     while ((c=getchar()) != '\n' && c != EOF);//获键盘输入文件名
15           fgets(file_u,30,stdin);  //stdin 标准输入
16     upload_file(file_u);      //上传
17   }
18 case '2':
19   {          //下载文件
20     while ((c=getchar()) != '\n' && c != EOF);
21           fgets(file_d,30,stdin);    //stdin 标准输入    
22     download_file(file_d);    //下载
23   }
24 }

 

  
按照客户端的合适进行设定
    //1.接收操作符--->>>第一部曲    --->>>1步
read(new_fd,&cmd,1);  //读取操作类型码
    //2.按照操作符进行命令函数
if(cmd == 'Q')
   { close(new_fd);     break;}
else
    handle(cmd);
    //3.进行正式文件处理--->>>剩下4部曲

void handle(char cmd) { switch(cmd) { case 'U'://服务器接收 { read(new_fd~ //接收文件名 --->>>2步 read(new_fd~ //接收文件长度 --->>>3步 fd = open(filename~//创建文件准备接受--->>>4步 write(fd,&buf~ //接收文件内容 --->>>5步 } case 'D'://服务器传出 { read(new_fd~ //接收文件名 --->>>2步 fd = open(filename~//打开当前目录文件--->>>3步 write(new_fd~ //发送文件长度 --->>>4步 write(new_fd //发送文件内容 --->>>5步 } case 'Q'://退出 { close(new_fd); break; } }

 

//case "1"  上传文件   5部曲
void upload_file(char *filename)
{
    //1.打开要上传的文件
fd = open(filename,O_RDONLY);  //以只读方式打开文件
    //2.发送操作符 cmd="U"
write(sockfd,&cmd,1);
    //3.发送要上传的文件名
write(sockfd,filename,size);
    //4.发送文件长度
stat(filename,&fstat);  //获取文件属性
write(sockfd,(void *)&(fstat.st_size),4);
    //5.发送文件
while((count=read(fd,(void *)buf,1024))>0)//读取来的数据存到buf的空间
        write(sockfd,&buf,count);
}

//case "2"  下载文件   5部曲相同
void download_file(char *filename)
{
    //1.发送操作符 cmd="D"
write(sockfd,&cmd,1);
    //2.发送要下载的文件名
write(sockfd,filename,size);
    //3.创建接收文件
fd = open(filename,O_RDONLY|O_CREAT,0777);  //以只读方式打开文件
    //4.接收文件长度
read(sockfd,&filesize,4);
    //5.接收文件
while((count=read(fd,(void *)buf,1024))>0)//读取来的数据存到buf的空间
        write(fd,&buf,count);
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 -------------------------------------------------------------------------------------------------------------------

二. OpenSSL加密系统

  由于网络传输数据中,易被抓包软件截获。因此运用非对称加密方法(公钥、私钥、数字证书)文件内容+公钥 ->加密系统 ->私钥,方可解密文件

a)公钥与私钥是配对时候用的;

b)私钥加密的文件同样用对应的公钥解密,而为了区分公钥(防止公钥被偷换,导致私密文件泄露),引入数字证书再加密

c)数字证书有权威机构发放,包含公钥及持有人信息,无法丢失假冒;

  SSL协议处于应用层协议(HTTP/SMTP)与TCP/IP协议之间,可实现文件加密传输。开源套接字层密码库OpenSSL,包含SSL、密码算法、秘钥证书管理功能等。 

  

 

 

 

 

 

-----------------------------------------------------------------------------------------------

  移植OpenSSL库:

解压安装文件 -> 配置.config文件,修改交叉工具链arm-linux- -> 编译make,make install,即生成OpenSSL的库函数文件 .a、.so -> 置于/rootfs/lib/目录下,OK!

  OpenSSL通讯模型:基于下列通讯模型优化原始传输子系统程序设计

客户端SSL模型 服务器端SSL模型

初始化SSL ->

(创建套接字、连接服务器) ->

创建SSL ->

基于SSL收发数据 ->

关闭SSL ->

(关闭套接字)

初始化SSL ->

公钥私钥数字证书设置 ->

(创建套接字、绑定、等待连接) ->

创建SSL ->

基于SSL收发数据 ->

关闭SSL ->

(关闭套接字)

 

 

 

 

 

 

 

 

 

 

 

 

基于SSL收发数据:将write (sockfd,~) ->SSL_write (ssl,~)、read (sockfd,~) ->SSL_read (ssl,~)即可!

再对应产生公钥、私钥:(全部置于服务器目录下)

  # openssl genrsa -out privkey.pem 2048  ->私钥

  # openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095 ->对应产生的公钥

  OpenSSL加密传输子系统程序设计完成,对应产生服务器加密所需的公钥与私钥分别进行编译即可实现:对上传、下载服务器文件的加密传输。

 

posted @ 2019-07-23 09:41  行路人&  阅读(365)  评论(0编辑  收藏  举报