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.hqwc.cn/news/165195.html

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

相关文章

登录Tomcat控制台,账号密码输入正确但点击登录没反应不跳转到控制台页面

在tomcat-users.xml里面可以查看登录tomcat控制台的账号密码&#xff0c;如果账号密码输入正确还是登录不进去&#xff0c;则很有可能是tomcat的账号被锁了&#xff08;可在catalina.xxx.log里面查看&#xff09;。tomcat账号被锁定后默认情况是不访问控制台后5分钟自动解锁&am…

【BUG解决】服务器没报警但是应用接口崩了....

最近遇到一个突发问题&#xff1a;服务器没报警但是应用接口崩了… 为其他业务系统提供一个接口&#xff0c;平时好好的&#xff0c;突然就嚷嚷反馈说访问不了了&#xff0c;吓得我赶紧跳起来&#xff01; 正常情况下在系统崩溃前&#xff0c;我会收到很多系统报警&#xff0…

通过SOLIDWORKS Composer让自定义视图更智能

SOLIDWORKS Composer是一款专业的技术文档创建工具&#xff0c;通过SOLIDWORKS Composer可以快速创建所需的技术文档&#xff0c;无论是用于装配说明&#xff0c;维护手册还是销售展示。 当使用SOLIDWORKS Composer创建交互式内容的时候&#xff0c;自定义视图至关重要。自定义…

Linux命令大全

荒诞也好&#xff0c;愚笨也好&#xff0c;总会过去的 文章目录 文件相关压缩相关tarzip 进程相关pskill 网络相关netstat IPC相关ipcsipcrm 系统资源相关topfreefdiskdfdu 权限相关umaskchmodchownchgrp 总结 文件相关 ls&#xff1a;列出当前目录中的文件和子目录。 ls常用…

​软考-高级-信息系统项目管理师教程 第四版【第22章-组织通用治理-思维导图】​

软考-高级-信息系统项目管理师教程 第四版【第22章-组织通用治理-思维导图】 课本里章节里所有蓝色字体的思维导图

Android Studio报错:connect refused

参考链接&#xff1a; https://blog.csdn.net/qq_43213783/article/details/113936012 参考文章中说报错主要是由于代理导致的&#xff0c;在文件->设置->外观与行为->系统设置->HTTP代理。 方法一&#xff1a; 查看打开代理&#xff08;前提是代理可以通网&#x…

黑洞路由的几种应用场景

第一种在内网中产生环路&#xff1a; 这种核心交换机上肯定写一条默认路由 0.0.0.0 0 10.0.0.1 出口路由要写一条192.168.0.0 16 10.0.0.2 如果出口路由访问一条不存在的内网网段&#xff0c;又或者访问的那台终端停机了&#xff0c;那就会产生三层环路&#xff0c;数据包在…

图扑智慧农业:农林牧数据可视化监控平台

数字农业是一种现代农业方式&#xff0c;它将信息作为农业生产的重要元素&#xff0c;并利用现代信息技术进行农业生产过程的实时可视化、数字化设计和信息化管理。能将信息技术与农业生产的各个环节有机融合&#xff0c;对于改造传统农业和改变农业生产方式具有重要意义。 图…

GPT-4 Turbo:OpenAI发布旗舰版GPT-4模型,更便宜|更强大|128K上下文|支持多模态

一、介绍 OpenAI 在 2023 年 11 月 7 日举行首届开发者大会&#xff0c;此次展会的亮点无疑是 GPT-4 Turbo 的亮相&#xff0c;它是 OpenAI 著名的 GPT-4 模型的升级版。 GPT-4 Turbo 有两种变体&#xff1a;一种用于文本分析&#xff0c;另一种能够理解文本和图像。 GPT-4 Tu…

09 # 手写 some 方法

some 使用 some() 方法测试数组中是否至少有一个元素通过了由提供的函数实现的测试。如果在数组中找到一个元素使得提供的函数返回 true&#xff0c;则返回 true&#xff1b;否则返回 false。它不会修改数组。 ele&#xff1a;表示数组中的每一个元素index&#xff1a;表示数…

dgl安装教程

我在矩池云服务器上安装了一个dgl的环境&#xff0c;以后都可以用这个了 首先我的基础环境是 最终的版本如下 安装步骤如下 pip install dgl0.9.1 -f https://s3.us-west-2.amazonaws.com/dgl-data/wheels/cu113/repo.html注意不能直接使用 pip install dgl -f https://s…

AI 绘画 | Stable Diffusion 高清修复、细节优化

前言 在 Stable Diffusion 想要生成高清分辨率的图片。在文生图的功能里&#xff0c;需要设置更大的宽度和高度。在图生图的功能里&#xff0c;需要设置更大的重绘尺寸或者重绘尺寸。但是设置完更大的图像分辨率&#xff0c;需要更大显存&#xff0c;1024*1024的至少要电脑的空…