c++ - 使用 libssh SFTP 下载的文件已损坏
问题描述
我正在使用 libssh 从本地 Windows 机器上的 Debian Linux 服务器下载文件,程序运行没有错误,但下载的文件已损坏。当我通过pscp
它下载时,我不知道我是否在缓冲区或其他方面做错了。
生成文件的大小是相同的,当我通过 FileZilla 或 WinSCP 等其他工具下载时,一切顺利。该文件不再损坏。当我运行我的代码时,它会损坏
我正在使用 Visual Studio 2019 在 Windows 10 上运行此代码。在多次弄乱此代码后,我认为问题出在write
文件写入功能上,当我在十六进制编辑器中打开生成的文件时,我只看到字节的差异保持不变的文件。
我之前最终发布了 Dart 版本的代码,但 C 版本几乎与 Dart 版本相同。
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NONSTDC_NO_DEPRECATE
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <stdexcept>
#include <string.h>
#include <exception>
#include <fstream>
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include "custom_exception.cpp"
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <io.h>
#include <time.h>
#include <chrono>
using std::chrono::high_resolution_clock;
using std::chrono::duration_cast;
using std::chrono::duration;
using std::chrono::milliseconds;
//using namespace std;
using std::string;
using std::cout;
using std::endl;
using std::cin;
// Good chunk size
#define MAX_XFER_BUF_SIZE 16384
int sftpDownloadFileTo(ssh_session session, const char* fullRemotePath, const char* fullLocalPath)
{
int access_type;
sftp_file file;
char buffer[MAX_XFER_BUF_SIZE * 8];//128KB
ssize_t nbytes, nwritten, rc;
int fd;
access_type = O_RDONLY;
sftp_session sftp = sftp_new(session);
if (sftp == NULL)
{
fprintf(stderr, "Error allocating SFTP session: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
rc = sftp_init(sftp);
if (rc != SSH_OK)
{
fprintf(stderr, "Error initializing SFTP session: %d.\n",
sftp_get_error(sftp));
sftp_free(sftp);
return rc;
}
file = sftp_open(sftp, fullRemotePath, access_type, 0);
if (file == NULL) {
fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(session));
return SSH_ERROR;
}
fd = open(fullLocalPath, O_CREAT | O_RDWR, 0777);
if (fd < 0) {
fprintf(stderr, "Can't open file for writing: %s\n",
strerror(errno));
return SSH_ERROR;
}
for (;;) {
nbytes = sftp_read(file, buffer, sizeof(buffer));
if (nbytes == 0) {
break; // EOF
}
else if (nbytes < 0) {
fprintf(stderr, "Error while reading file: %s\n",
ssh_get_error(session));
sftp_close(file);
return SSH_ERROR;
}
nwritten = write(fd, buffer, nbytes);
if (nwritten != nbytes) {
fprintf(stderr, "Error writing: %s\n",
strerror(errno));
sftp_close(file);
return SSH_ERROR;
}
}
rc = sftp_close(file);
if (rc != SSH_OK) {
fprintf(stderr, "Can't close the read file: %s\n",
ssh_get_error(session));
return rc;
}
sftp_free(sftp);
return SSH_OK;
}
int main()
{
ssh_session my_ssh_session;
int rc;
int port = 22;
string password = "Ins257257";
auto host = "192.168.133.13";
auto username = "isaque.neves";
int verbosity = SSH_LOG_PROTOCOL;
// Abra a sessão e defina as opções
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, host);
//ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
// Conecte-se ao servidor
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK)
{
fprintf(stderr, "Error connecting to host: %s\n",
ssh_get_error(my_ssh_session));
exit(-1);
}
// Autenticar-se
rc = ssh_userauth_password(my_ssh_session, username, password.c_str());
if (rc != SSH_AUTH_SUCCESS)
{
fprintf(stderr, "Error authenticating with password: %s\n",
ssh_get_error(my_ssh_session));
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
exit(-1);
}
clock_t tic = clock();
auto t1 = high_resolution_clock::now();
sftpDownloadFileTo(my_ssh_session, "/home/isaque.neves/go1.11.4.linux-amd64.tar.gz", "D:/MyDartProjects/fsbackup/libssh_binding/go1.11.4.linux-amd64.tar.gz");
auto t2 = high_resolution_clock::now();
clock_t toc = clock();
duration<double, std::milli> ms_double = t2 - t1;
std::cout << ms_double.count() << " ms\r\n";
printf("Elapsed: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
std::cout << "End\n";
return 0;
}
https://github.com/insinfo/fsbackup/tree/main/libssh_binding
解决方案
fd = open(fullLocalPath, O_CREAT | O_RDWR, 0777);
这是你的问题。由于您在 Windows 上运行,我们需要在此处进行调整。
fd = open(fullLocalPath, O_CREAT | O_RDWR | O_BINARY, 0777);
否则 write() 将尝试调整行尾。
推荐阅读
- f# - 避免在程序集的两个部分中出现模块和类型定义的错误
- python - Python - 如何在 for 循环中打印 json 的内部键?
- c# - ServiceStack.OrmLite 使用错误的列定义创建表
- scala - 如何实现 CustomKeySerializer
- python - 当尝试在弹性搜索中进行批量更新时。我收到 403 错误?
- python - 如何让 docker 容器在主机内而不是容器内搜索文件?
- telethon - Telethon 无法再获取聊天实体
- python - 使用 genfromtxt 获取数据时遇到问题
- extjs - 如何在单击时显示包含两个单独工作的单选按钮的标题菜单
- java - 如何在不使用公共静态void main(String [] args)的情况下在vs代码中获取用户输入