一. 基本传输子系统程序设计
客户端可上传文件至服务器,或下载服务器上的文件
系统程序构架:
客户端 | 服务器 |
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, |
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 void menu() 2 { 3 while(1) 4 { 5 printf(" -------- 1. Upload Files ----------- "); 6 printf("-------- 2. Download Files ---------- "); 7 printf("--------------- 3. Exit ------------ "); 8 printf("Please input the Client command:"); 9 command = getchar(); //等待用户输入字符 10 switch(command) 11 { 12 case '1': 13 { //上传文件 14 while ((c=getchar()) != ' ' && c != EOF);//获键盘输入文件名 15 fgets(file_u,30,stdin); //stdin 标准输入 16 upload_file(file_u); //上传 17 } 18 case '2': 19 { //下载文件 20 while ((c=getchar()) != ' ' && c != EOF); 21 fgets(file_d,30,stdin); //stdin 标准输入 22 download_file(file_d); //下载 23 } |
按照客户端的合适进行设定 //1.接收操作符--->>>第一部曲 --->>>1步 read(new_fd,&cmd,1); //读取操作类型码 //2.按照操作符进行命令函数 if(cmd == 'Q') { close(new_fd); break;} else handle(cmd); //3.进行正式文件处理--->>>剩下4部曲 |
//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加密传输子系统程序设计完成,对应产生服务器加密所需的公钥与私钥,分别进行编译即可实现:对上传、下载服务器文件的加密传输。