1.前言

1.1 why?

闲来无事,自己研究了一下服务端与客户端之间的文件传输,主要是服务端创建套接字开启监听并等待客户端的连接(TCP),在TCP协议上,为了安全我使用了TLS1.2进行加密通信(OpenSSL库),同时为了文件内容的安全,我在服务端对文件进行了加密(AES),客户端接收到文件后在对其解密。

1.2 硬件

我用的电脑系统是ubuntu 16.04,不是windows,下面的代码放到windows环境下跑不了的,有些库windows不兼容,但是windows开发的小伙伴也可以参考参考,把不兼容的库替换掉修改修改(比如linux的opendir,readdir,closedir可以替换成windows下的函数,具体百度),应该也可以跑过。无论是windows还是linux,下面的代码中都需要证书,将证书的路径正确的放到代码里面,程序才能编译通过,证书如何生成,请参考我以前的博客。

2 server端代码

2.1 头文件以及函数声明

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/ssl.h>
#include <fcntl.h>
#include <stdbool.h>
#include <dirent.h>
#include <sys/types.h>#define CA_CRT         "./opensslkey/demoCA/cacert1.pem"
#define SERVER_CRT     "./opensslkey/server.crt"
#define SERVER_KEY     "./opensslkey/server.key"#define MAXBUF 1024
char buffer[MAXBUF];
char buffer1[MAXBUF];
char *Path = NULL;
void Directory(char* path, SSL* ssl, struct dirent *ptr);
bool readfile(char* my_Path,SSL *ssl,struct dirent *ptr);
bool Document(char* Path, SSL *ssl,struct dirent *ptr);
void aes_box_encrypt(char* source_string, char* des_string, int size);
bool Shutdown(SSL* ssl);
void Getmessage(SSL* ssl, char* buf);
DIR* readFileList(char *basePath);
bool Sendlog(SSL* ssl, char* buf);
void ShowCerts(SSL * ssl);

2.2 函数实现

void aes_box_encrypt(char* source_string, char* des_string, int size)//负责数据加密
{int iLoop = 0;int iLen =0;char buf[1024];AES_KEY aes;unsigned char key[AES_BLOCK_SIZE];unsigned char iv[AES_BLOCK_SIZE];if(NULL == source_string || NULL == des_string){return;}//Generate own AES Keyfor(iLoop = 0; iLoop < 16; iLoop++){key[iLoop] = 32 + iLoop;}// Set encryption keyfor (iLoop=0; iLoop<AES_BLOCK_SIZE; iLoop++) {iv[iLoop] = 0;}if (AES_set_encrypt_key(key, 128, &aes) < 0) {return ;}iLen = size;AES_cbc_encrypt(source_string, des_string, iLen, &aes, iv, AES_ENCRYPT);
}bool Shutdown(SSL* ssl)//log发送完毕,服务端发送消息断开与客户端的连接(服务器继续等待客户端的下一次连接)
{char d[1024];memset(d,'\0', sizeof(d));strcpy(d, "complate");int len = SSL_write(ssl, d, strlen(d));if (len <= 0) {printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buffer, errno, strerror(errno));return false;} elseprintf("消息发送成功%s,共发送了%d个字节!\n",d, len);return true;
}void Getmessage(SSL* ssl, char* buf)//获取客户端的消息
{int len = SSL_read(ssl, buf, MAXBUF);if (len > 0)printf("接收消息成功:'%s',共%d个字节的数据\n", buf, len);elseprintf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
}void Directory(char* path, SSL* ssl, struct dirent *ptr)//目录处理
{char *base = NULL;base = path;strcat(ptr->d_name,"/");char* e = (char*)malloc(strlen(base) + strlen(ptr->d_name) + 1);strcpy(e,base);strcat(e,ptr->d_name);bool ret = readfile(e, ssl, ptr);
}bool Document(char* Path, SSL *ssl,struct dirent *ptr)//真正发送log文件
{char a[1024];int fd = 0;memset(a,'\0', sizeof(a));memset(buffer,'\0', sizeof(buffer));memset(buffer1,'\0', sizeof(buffer1));strcpy(a, Path);strcat(a, ptr->d_name);fd = open(a, O_RDONLY);read(fd, buffer,sizeof(buffer));//发送两次数据,第一次是文件名,第二次是文件内容int len1 = SSL_write(ssl, ptr->d_name, strlen(ptr->d_name));printf("document name is:%s\n", ptr->d_name);if (len1 <= 0) {printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buffer, errno, strerror(errno));return false;} elseprintf("消息发送成功,共发送了%d个字节!\n", len1);aes_box_encrypt(buffer, buffer1, sizeof(buffer));int len = SSL_write(ssl, buffer1, strlen(buffer1));if (len <= 0) {printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buffer, errno, strerror(errno));return false;} elseprintf("消息发送成功,共发送了%d个字节!\n", len);close(fd);return true;
}DIR* readFileList(char *basePath)//打开目录,opendir配合readdir使用
{DIR *dir;struct dirent *ptr;//readdirif ((dir=opendir(basePath)) == NULL){printf("Open path error\n");exit(1);}return dir;
}bool readfile(char* Path,SSL *ssl,struct dirent *ptr)//文件或者目录处理
{DIR *dir = readFileList(Path);while ((ptr=readdir(dir)) != NULL){if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0) ///current dir OR parrent dircontinue;else if(ptr->d_type == 8) //document{printf("path is:%s\n",Path);Document(Path, ssl, ptr);}else if(ptr->d_type == 4)//directory{Directory(Path, ssl, ptr);}}return true;
}bool Sendlog(SSL* ssl, char* buf)//发送log文件
{if(strcmp(buf, "getlog") == 0){struct dirent *ptr;char *basePath = NULL;basePath = "./log/";readfile(basePath, ssl, ptr);}Shutdown(ssl);
}void ShowCerts(SSL * ssl)//验证显示证书
{X509 *cert;char *line;cert = SSL_get_peer_certificate(ssl);// SSL_get_verify_result()是重点,SSL_CTX_set_verify()只是配置启不启用并没有执行认证,调用该函数才会真证进行证书认证// 如果验证不通过,那么程序抛出异常中止连接if(SSL_get_verify_result(ssl) == X509_V_OK){printf("证书验证通过\n");}if (cert != NULL) {printf("数字证书信息:\n");line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);printf("证书: %s\n", line);free(line);line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);printf("颁发者: %s\n", line);free(line);X509_free(cert);} elseprintf("无证书信息!\n");
}

3 后序

3.1 参考博客

  1. AES加密算法:https://www.cnblogs.com/ygxsk/p/7693978.html
  2. AES加密算法:https://blog.csdn.net/qncj666/article/details/8244893
  3. 文件操作:https://blog.csdn.net/angle_birds/article/details/8502874
  4. 双向认证程序实现:https://www.cnblogs.com/lsdb/p/9391979.html

3.2写给读者的话

  1. 代码一部分是参考别人的,一部分是我自己写的
  2. 代码供大家参考,转载或者自己参考写,请标明原文档地址
  3. 代码我只贴了server端的,客户端代码较少,我没贴,大家可以参考上面的链接自行书写
  4. 代码可能会有我没测出来的bug,欢迎大家继续完善

服务端和客户端之文件加密传输相关推荐

  1. linux 文件 加密传输,服务端和客户端之文件加密传输

    void aes_box_encrypt(char* source_string, char* des_string, int size)//负责数据加密 { int iLoop = 0; int i ...

  2. Java服务端向客户端写文件_java实现客户端向服务器发送文件

    本文实例为大家分享了java实现客户端向服务器发送文件的具体代码,供大家参考,具体内容如下 服务器源代码: import java.io.BufferedReader; import java.io. ...

  3. Java中Socket通信-服务端和客户端双向传输字符串实现

    场景 什么是socket 在计算机通信领域,socket 被翻译为"套接字",它是计算机之间进行通信的一种约定或一种方式.通过 socket 这种约定,一台计算机可以接收其他计算机 ...

  4. 使用C++的Socket实现从客户端到服务端,服务端到客户端传输文件

    使用: (1)首先运行服务端,待服务端运行起来: (2)最后运行客户端,输入要传输文件到哪个目标机器的IP地址: (3)输入传输文件的路径及文件(完成的路径),其中包含文件的类型,也就是后缀需要包含( ...

  5. C# Socket服务端与客户端通信(包含大文件的断点传输)

    步骤: 一.服务端的建立 1.服务端的项目建立以及页面布局 2.各功能按键的事件代码 1)传输类型说明以及全局变量 2)Socket通信服务端具体步骤:   (1)建立一个Socket   (2)接收 ...

  6. Socket异步服务器,可以监控客户端的状态,功能有,文字测试,服务端向客户端传输屏幕录像(UDP传输)、监控客户端屏幕(UDP传输),抖动用户窗体、发送文件给用户、扫描客户的C盘目录。

    用VS2015工具C#语言编写了一个简单的Socket异步服务器,可以监控客户端的状态,功能有,文字测试,服务端向客户端传输屏幕录像(UDP传输).监控客户端屏幕(UDP传输),抖动用户窗体.发送文件 ...

  7. 成品app直播源码,服务端与客户端传输视频文件

    成品app直播源码,服务端与客户端传输视频文件相关的代码 Server端 #define WIN32_LEAN_AND_MEAN #define _WINSOCK_DEPRECATED_NO_WARN ...

  8. java大话西游单机版,【大话西游】手工架设服务端+双客户端+加密解密全套工具...

    [大话西游]手工架设服务端+双客户端+加密解密全套工具_站长网(Downzz.com) 安装说明: 服务器系统 Windows Server 2008 R2 1.首先第一步把需要的运行工具以及所需工具 ...

  9. nodejs01——安装及使用、服务端及客户端、commonjs规范、fs模块的使用(文件操作及目录操作)、stream、buffer、WebServer、端口、动态资源及静态资源、头信息、请求方式

    nodejs的安装及使用 服务端及客户端 commonjs规范 fs模块的使用(文件操作及目录操作) stream buffer // Node.js介绍 Node.js 诞生于2009年,Node. ...

最新文章

  1. dos批处理命令详解
  2. Eclipse上GIT插件EGIT使用手册之五_查看历史记录
  3. python交互界面用图片当背景_wxPython实现窗口用图片做背景
  4. 简说设计模式——策略模式
  5. Linux IP别名,接口绑定,多网卡绑定
  6. Android Transition Framework详解---超炫的动画框架
  7. Java 代码生成器(CURD CRUD)
  8. python小区管理系统设计_小区物业管理系统设计与实现
  9. grads 读取shp
  10. 武汉大学计算机学院选考要求,武汉大学高考必选科目-考武汉大学需要选哪三科...
  11. 如果你的下属不服从你得管理,你会怎么办?
  12. Android指南针应用编写
  13. csdn博客文章头部自动生成目录
  14. Winedit7.0自定义一键编译
  15. 自监督论文阅读笔记 Urban feature analysis from aerial remote sensing imagery using self-supervised and semi-s
  16. 7-45 连年 7-69 求婚
  17. 《安富莱嵌入式周报》第276期:2022.07.25--2022.07.31
  18. 腾讯云python怎么用_Python操作腾讯云CVM
  19. ECharts Map 属性详解
  20. vue中如何利用js如何检测网络状况,监听网络状态

热门文章

  1. Hive SQL 小表与大表Join 原理与实操
  2. GD32F303CCT6与GD32F407VKTC spi 主从通信
  3. SQL研习录(26)——子查询
  4. 爬虫python书籍-python爬虫有哪些书
  5. Zxing 生成条形码(一维码)
  6. 什么是ui设计培训?ui培训课程难学吗?
  7. 西安5位教授联名呼吁免除药家鑫死刑
  8. 实验9-5 查找书籍 (20 分)
  9. java设置铃声_APP集成小米消息推送自定义铃声设置
  10. linux运行雷神之锤,Ubuntu下多人射击类游戏 Quake Live 雷神之锤