20.8 OpenSSL 套接字SSL传输文件

有了上面的基础那么传输文件的实现就变得简单了,在传输时通常我们需要打开文件,并每次读入1024个字节的数据包,通过SSL加密传输即可,此处的文件传输功能在原生套接字章节中也进行过详细讲解,此处我们还是使用原来的密钥对,实现一个服务端等待客户端上传,当客户端连接到服务端后则开始传输文件,服务端接收文件的功能。

服务端代码部分,此处我们只需要实现一个DownloadFile函数,该函数接收一个SSL套接字,与保存文件路径即可,其他部分同上。

#include <WinSock2.h>
#include <iostream>
#include <string.h>
#include <errno.h>
#include <stdlib.h>#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/pem.h>
#include <openssl/crypto.h>extern "C"
{
#include <openssl/applink.c>
}#pragma comment(lib, "WS2_32.lib")
#pragma comment(lib,"libssl.lib")
#pragma comment(lib,"libcrypto.lib")#define MAXBUF 1024// 从路径中获取当前文件名
char* GetFileName(char* Path)
{if (strchr(Path, '\\')){char ch = '\\';char* ref = strrchr(Path, ch) + 1;return ref;}else{char ch = '/';char* ref = strrchr(Path, ch) + 1;return ref;}
}// 下载文件到当前目录
// 传入套接字句柄,以及放置根目录
void DownloadFile(SSL* ptr, const char* RootPath)
{int FileSize = 0;char FilePath[1024] = { 0 };char buffer[1024] = { 0 };// 接收文件长度SSL_read(ptr, &FileSize, 4);// 接收文件路径SSL_read(ptr, FilePath, 1024);// 获取到文件名char* FileName = GetFileName(FilePath);// 拼接路径char sz[1024] = { 0 };strcpy(sz, RootPath);strcat(sz, FileName);std::cout << sz << std::endl;// 保存文件到当前目录FILE* pointer = fopen(sz, "wb");if (pointer != NULL){DWORD length = 0;DWORD total_length = 0;// 循环接收字节数据,每次接收1024字节while ((length = SSL_read(ptr, buffer, 1024)) > 0){// 写出文件并判断是否写出成功if (fwrite(buffer, sizeof(char), length, pointer) < length){break;}// 每次累加递增total_length += length;memset(buffer, 0, 1024);// 判断文件长度是否全部接收完毕if (total_length >= FileSize){std::cout << "[传输完成] " << total_length << std::endl;fclose(pointer);return;}}fclose(pointer);}
}int main(int argc, char** argv)
{SOCKET sockfd, new_fd;struct sockaddr_in socket_ptr, their_addr;char buf[MAXBUF + 1];SSL_CTX* ctx;SSL_library_init();OpenSSL_add_all_algorithms();SSL_load_error_strings();ctx = SSL_CTX_new(SSLv23_server_method());if (ctx == NULL){return 0;}if (SSL_CTX_use_certificate_file(ctx, "d://cacert.pem", SSL_FILETYPE_PEM) <= 0){return 0;}if (SSL_CTX_use_PrivateKey_file(ctx, "d://privkey.pem", SSL_FILETYPE_PEM) <= 0){return 0;}if (!SSL_CTX_check_private_key(ctx)){return 0;}WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){WSACleanup();return 0;}if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){return 0;}socket_ptr.sin_family = AF_INET;socket_ptr.sin_addr.s_addr = inet_addr("127.0.0.1");socket_ptr.sin_port = htons(9999);if (bind(sockfd, (struct sockaddr*)&socket_ptr, sizeof(struct sockaddr)) == -1){return 0;}if (listen(sockfd, 10) == -1){return 0;}while (1){SSL* ssl;int len = sizeof(struct sockaddr);if ((new_fd = accept(sockfd, (struct sockaddr*)&their_addr, &len)) != -1){printf("客户端地址: %s --> 端口: %d --> 套接字: %d \n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd);}ssl = SSL_new(ctx);SSL_set_fd(ssl, new_fd);if (SSL_accept(ssl) == -1){closesocket(new_fd);break;}// 调用下载文件函数DownloadFile(ssl, "d://lyshark/");finish:SSL_shutdown(ssl);SSL_free(ssl);closesocket(new_fd);}closesocket(sockfd);WSACleanup();SSL_CTX_free(ctx);system("pause");return 0;
}

客户端部分,同样代码中只需要实现一个UploadFile函数,该函数用于发送本地文件到远程,其他部分同上。

#include <WinSock2.h>
#include <iostream>
#include <string.h>
#include <errno.h>
#include <stdlib.h>#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/pem.h>
#include <openssl/crypto.h>extern "C"
{
#include <openssl/applink.c>
}#pragma comment(lib, "WS2_32.lib")
#pragma comment(lib,"libssl.lib")
#pragma comment(lib,"libcrypto.lib")#define MAXBUF 1024// 获取文件大小
int GetFileSize(std::string FileName)
{FILE* pointer = NULL;pointer = fopen(FileName.c_str(), "rb");if (pointer != NULL){fseek(pointer, 0, SEEK_END);int size = ftell(pointer);fclose(pointer);return size;}return 0;
}// 上传文件,传入socket套接字句柄,需要发送的文件路径
void UploadFile(SSL* ptr, const char* FilePath)
{int FileSize = GetFileSize(FilePath);char buffer[1024] = { 0 };// 发送文件长度SSL_write(ptr, &FileSize, 4);// 发送完整文件路径SSL_write(ptr, FilePath, strlen(FilePath));FILE* pointer = fopen(FilePath, "rb");if (pointer != NULL){int length = 0;DWORD total_length = 0;while ((length = fread(buffer, sizeof(char), 1024, pointer)) > 0){SSL_write(ptr, buffer, length);memset(buffer, 0, 1024);}}
}int main(int argc, char** argv)
{int sockfd, len;struct sockaddr_in dest;char buffer[MAXBUF + 1] = { 0 };SSL_CTX* ctx;SSL* ssl;SSL_library_init();OpenSSL_add_all_algorithms();SSL_load_error_strings();ctx = SSL_CTX_new(SSLv23_client_method());if (ctx == NULL){WSACleanup();return 0;}WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){WSACleanup();return 0;}if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){WSACleanup();return 0;}dest.sin_family = AF_INET;dest.sin_addr.s_addr = inet_addr("127.0.0.1");dest.sin_port = htons(9999);if (connect(sockfd, (struct sockaddr*)&dest, sizeof(dest)) != 0){WSACleanup();return 0;}ssl = SSL_new(ctx);SSL_set_fd(ssl, sockfd);if (SSL_connect(ssl) != -1){printf("SSL 连接类型: %s \n", SSL_get_cipher(ssl));}// 发送文件UploadFile(ssl, "d://lyshark.exe");finish:SSL_shutdown(ssl);SSL_free(ssl);closesocket(sockfd);SSL_CTX_free(ctx);system("pause");return 0;
}

读者可自行编译这段代码,并首先启动服务端等待传输,接着打开客户端,此时客户端中的d://lyshark.exe将被传输到服务端的特定目录下,如下图所示;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/181929.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Verilog 教程】7.3 Verilog 串行 FIR 滤波器设计

串行 FIR 滤波器设计 设计说明 设计参数不变&#xff0c;与并行 FIR 滤波器参数一致。即&#xff0c;输入频率为 7.5 MHz 和 250 KHz 的正弦波混合信号&#xff0c;经过 FIR 滤波器后&#xff0c;高频信号 7.5MHz 被滤除&#xff0c;只保留 250KMHz 的信号。 输入频率&#x…

VMware安装CentOS最小化开发环境导引

目录 一、概要 二、介绍 三、下载 四、安装 4.1 创建虚拟机 4.2 安装CentOS 五、配置网卡 六、配置本地安装源 七、安装软件 7.1 gcc/g 7.2 C的atomic库 7.3 java 7.4 Cmake 7.5 MariaDB客户端&#xff08;兼容mysql&#xff09; 八、用户配置文件.bash_profile…

[开源]企业级在线办公系统,基于实时音视频完成在线视频会议功能

一、开源项目简介 企业级在线办公系统 本项目使用了SpringBootMybatisSpringMVC框架&#xff0c;技术功能点应用了WebSocket、Redis、Activiti7工作流引擎&#xff0c; 基于TRTC腾讯实时音视频完成在线视频会议功能。 二、开源协议 使用GPL-3.0开源协议 三、界面展示 部分…

什么是单片机?它是如何工作的?

一.单片机是什么&#xff1f; 家用电器包含各种各样的集成电路板。 在集成电路板上最重要的就是单片机&#xff08;单片微型计算机&#xff09;。它是一种集成电路芯片。 二.单片机的组成 2.1 CPU CPU的主要功能是运算和控制。2.2 ROM 1.是什么&#xff1f; ROM的全称是Re…

Redis03-过期策略和淘汰策略

目录 Redis数据过期策略 Redis数据淘汰策略 Redis数据过期策略 Redis使用一种基于过期策略来处理键的过期和自动失效。这种策略可以确保不再需要的数据被自动删除&#xff0c;以释放内存并避免数据过期后仍然在缓存中存留。 Redis的过期删除策略主要有两种&#xff1a; 惰性…

【SpringSecuirty6.x】自动登录和注销登录

关于网站的安全设计,通常是有一些矛盾点的。我们在作为某些系统开发者的同时,也在充当着另外一些系统的用户,一些感同身受的东西可以带来很多思考。 5.1、为什么需要自动登录 当我们在某个网站上注册账号时,网站会对我们设置的登录密码提出要求。例如,有的网站要求使用固…

VS编译器中创建新源文件,自动添加----#define _CRT_SECURE_NO_WARNINGS 1

每次创建新的源文件时都需要添加比较麻烦&#xff0c;我们让每次创建时自动添加&#xff0c;步骤如下&#xff1a; 1、右键编译器--->属性--->目标&#xff08;存放的是编译器的文件位置我们找到文件的位置&#xff09; 2、如下步骤找到“newc file.cpp”文件&#xff0…

如何使用Ruby 多线程爬取数据

现在比较主流的爬虫应该是用python&#xff0c;之前也写了很多关于python的文章。今天在这里我们主要说说ruby。我觉得ruby也是ok的&#xff0c;我试试看写了一个爬虫的小程序&#xff0c;并作出相应的解析。 Ruby中实现网页抓取&#xff0c;一般用的是mechanize&#xff0c;使…

Linux安装配置awscli命令行接口工具及其从aws上传下载数据

官网技术文档有全面介绍&#xff1a;安装或更新 AWS CLI 的最新版本 - AWS Command Line Interface在系统上安装 AWS CLI。https://docs.aws.amazon.com/zh_cn/cli/latest/userguide/getting-started-install.html#getting-started-install-instructionsawscli常用命令参考&…

深度学习之基于Tensorflow卷积神经网络花卉识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 深度学习是一种机器学习方法&#xff0c;它通过模拟人脑神经网络的结构和功能来实现对数据的自动分析和学习。卷积神…

ClickHouse 学习之基础入门(一)

第 1 章 ClickHouse 入 门 ClickHouse 是俄罗斯的 Yandex 于 2016 年开源的列式存储数据库&#xff08;DBMS&#xff09;&#xff0c;使用 C 语言编写&#xff0c;主要用于在线分析处理查询&#xff08;OLAP&#xff09;&#xff0c;能够使用 SQL 查询实时生成分析数据报告。 …

Linux环境基础开发工具使用(二)

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、Linux项目自动化构建工具-make/Makefile1、背景2、实例代码3、依赖关系4、依赖方法5、原理…

【Head First 设计模式】-- 策略模式

一、背景 Head First 设计模式第一章设计模式入门–策略模式 二、工具箱的工具&#xff08;本章&#xff09; 1、OO基础 封装 继承 多态 抽象 2、OO原则 封装变化 面向接口编程&#xff0c;而非面向实现编程 组合优于继承 3、OO模式 策略模式&#xff0c;所谓策略模式就是定义…

spring-boot中实现分片上传文件

一、上传文件基本实现 1、前端效果图展示&#xff0c;这里使用element-ui plus来展示样式效果 2、基础代码如下 <template><div><el-uploadref"uploadRef"class"upload-demo":limit"1":on-change"handleExceed":auto-…

【算法】单调栈 每日温度 接雨水

文章目录 例题739. 每日温度42. 接雨水 相关练习1475. 商品折扣后的最终价格901. 股票价格跨度1019. 链表中的下一个更大节点84. 柱状图中最大的矩形 单调栈【基础算法精讲 26】 例题 739. 每日温度 https://leetcode.cn/problems/daily-temperatures/description/ 提示&a…

Git 的基本操作 ——命令行

Git 的工作流程 详解如下&#xff1a; 本地仓库&#xff1a;是在开发人员自己电脑上的Git仓库,存放我们的代码(.git 隐藏文件夹就是我们的本地仓库) 远程仓库&#xff1a;是在远程服务器上的Git仓库,存放代码(可以是github.com或者gitee.com 上的仓库,或者自己该公司的服务器…

php去除字符串两边空格空字符串换行方法

在PHP中&#xff0c;可以使用以下几种方法去除字符串两边的空格、空字符串和换行符&#xff1a; 使用trim()函数去除字符串两边的空格和空字符串&#xff0c;例如&#xff1a; $str " Hello World! "; $trimmed trim($str); echo $trimmed; 使用preg_replace(…

Angular-07:组件生命周期

三个阶段&#xff1a; ① 挂载阶段1.1 constructor1.2 ngOnInit ② 更新阶段2.1 ngOnChanges2.2 ngAfterViewInit2.3 ngAfterContentInit2.4 ngDoCheck ③ 卸载阶段3.1 onOnDestroy ④ 在组件中添加所有方法并打印 该表按照执行顺序编写 编号函数名实现名说明1constructorcons…

Java 开发常用的 Linux 命令

基本操作 Linux关机,重启 # 关机 shutdown -h now# 重启 shutdown -r now查看系统,CPU信息 # 查看系统内核信息 uname -a# 查看系统内核版本 cat /proc/version# 查看当前用户环境变量 envcat /proc/cpuinfo# 查看有几个逻辑cpu, 包括cpu型号 cat /proc/cpuinfo | grep name …

【Spring Boot 源码学习】JedisConnectionConfiguration 详解

Spring Boot 源码学习系列 JedisConnectionConfiguration 详解 引言往期内容主要内容1. RedisConnectionFactory1.1 单机连接1.2 集群连接1.3 哨兵连接 2. JedisConnectionConfiguration2.1 RedisConnectionConfiguration2.2 导入自动配置2.3 相关注解介绍2.4 redisConnectionF…