C/C++ 通过套接字下载/上传文件
C/C++ Downloading / Uploading Files via socket
我目前正在尝试通过套接字下载/上传文件 (SOCK_STREAM)。以下两个函数是我用来发送和接收数据的。
我目前 运行 遇到以下问题:
结果文件有时与源文件大小不同
这个问题越严重,文件越大。
我很确定我遗漏了一些明显的东西,可能在我的循环中或确定数据流的结尾。过去一周我尝试了很多不同的方法/解决方案,这是最接近我得到的工作版本...
感谢您的任何建议和评论,如果我需要提供更多信息,请告诉我
从服务器向客户端发送数据的函数:
void send_file(char *filename, int sock)
{
char data[1024] = {0};
FILE *fp = fopen(filename, "rb");
while (fread(data, sizeof(char), sizeof(data), fp) == 1024) {
if (send(sock, data, sizeof(data), 0) == -1) {
printf("%s%s[-] Error Transmitting File\n\n", KRED, BGHT);
break;
}
bzero(data, sizeof(data));
}
bzero(data, sizeof(data));
strcpy(data, "!EOF!");
send(sock, data, sizeof(data), 0);
bzero(data, sizeof(data));
printf("%s%s[+] Upload Successful\n\n", KGRN, BGHT);
fclose(fp);
}
客户端从服务器接收数据的函数:
void write_file(int sock, char *filepath)
{
FILE *fp;
int n;
char *lastSlash = strrchr(filepath, '\');
char *filename = lastSlash ? lastSlash +1 : filepath;
char data[1024] = {0};
fp = fopen(filename, "wb");
while (1) {
n = recv(sock, data, sizeof(data), 0);
if (strncmp("!EOF!", data, 5) == 0) {
break;
}
if (n <= 0) {
break;
return;
}
fwrite(data, sizeof(char), sizeof(data), fp);
bzero(data, sizeof(data));
}
fclose(fp);
return;
}
我终于在以下Post的帮助下弄明白了:
我重写了示例代码以满足我的需要。到目前为止效果很好。
感谢大家让我对这个主题有了更多的了解,并帮助我确定了我们在途中进行的必要检查!
这里对新代码进行简要说明:
首先需要认识到的是,像 send() recv() fread() fwrite() 这样的函数在传递之前可能不会完全填满它们的缓冲区。这意味着如果您有一个指定大小为 100 的缓冲区,它们可能只会将其填充到 89 95 或其他大小。因此,文件很可能已损坏。要解决此问题,需要检查每次调用 send() recv() fread() fwrite() 函数。
首先,您需要在服务器端和客户端都具备这两个功能。这些确保正在发送/接收整个缓冲区。
它基本上只是循环 send() / recv() 直到缓冲区被填满。
int RecvBuffer(int sock, char* buffer, int bufferSize, int chunkSize) {
int i = 0;
while (i < bufferSize) {
const int l = recv(sock, &buffer[i], __min(chunkSize, bufferSize - i), 0);
if (l < 0) { return l; }
i += l;
}
return i;
}
int SendBuffer(int sock, char* buffer, int bufferSize, int chunkSize) {
int i = 0;
while (i < bufferSize) {
const int l = send(sock, &buffer[i], __min(chunkSize, bufferSize - i), 0);
if (l < 0) { return l; }
i += l;
}
return i;
}
接下来,我们需要对下载/上传文件所调用的函数应用相同的检查。在这里,我循环遍历上述填充缓冲区的函数和 fread() fwrite(),直到所有字节 (fileSize) 都已发送。 chunkSize 参数定义发送的每个包的大小。到目前为止,我使用 65.536 (64kb) 没有任何问题。
int RecvFile(int sock, char *filePath, int chunkSize, int fileSize) {
char *lastSlash = strrchr(filePath, '\');
char *filename = lastSlash ? lastSlash +1 : filePath;
FILE *fp = fopen(filename, "wb");
char buffer[chunkSize];
int i = fileSize;
while (i != 0) {
const int r = RecvBuffer(sock, buffer, (int)__min(i, (int)chunkSize), chunkSize);
if ((r < 0) || !fwrite(buffer, sizeof(char), r, fp)) { break; }
i -= r;
}
bzero(buffer, sizeof(buffer));
fclose(fp);
printf("\n%s%s[+] Download Successful\n\n", KGRN, BGHT);
return -3;
}
int SendFile(int sock, char *fileName, int chunkSize, int fileSize) {
FILE *fp = fopen(fileName, "rb");
char buffer[chunkSize];
int i = fileSize;
while (i != 0) {
const int ssize = __min(i, (int)chunkSize);
if (!fread(buffer, sizeof(char), ssize, fp)) { break; }
const int l = SendBuffer(sock, buffer, (int)ssize, (int)chunkSize);
if (l < 0) { break; }
i -= l;
}
bzero(buffer, sizeof(buffer));
fclose(fp);
printf("\n%s%s[+] Upload Successful\n\n", KGRN, BGHT);
return -3;
}
我目前正在尝试通过套接字下载/上传文件 (SOCK_STREAM)。以下两个函数是我用来发送和接收数据的。 我目前 运行 遇到以下问题: 结果文件有时与源文件大小不同 这个问题越严重,文件越大。
我很确定我遗漏了一些明显的东西,可能在我的循环中或确定数据流的结尾。过去一周我尝试了很多不同的方法/解决方案,这是最接近我得到的工作版本...
感谢您的任何建议和评论,如果我需要提供更多信息,请告诉我
从服务器向客户端发送数据的函数:
void send_file(char *filename, int sock)
{
char data[1024] = {0};
FILE *fp = fopen(filename, "rb");
while (fread(data, sizeof(char), sizeof(data), fp) == 1024) {
if (send(sock, data, sizeof(data), 0) == -1) {
printf("%s%s[-] Error Transmitting File\n\n", KRED, BGHT);
break;
}
bzero(data, sizeof(data));
}
bzero(data, sizeof(data));
strcpy(data, "!EOF!");
send(sock, data, sizeof(data), 0);
bzero(data, sizeof(data));
printf("%s%s[+] Upload Successful\n\n", KGRN, BGHT);
fclose(fp);
}
客户端从服务器接收数据的函数:
void write_file(int sock, char *filepath)
{
FILE *fp;
int n;
char *lastSlash = strrchr(filepath, '\');
char *filename = lastSlash ? lastSlash +1 : filepath;
char data[1024] = {0};
fp = fopen(filename, "wb");
while (1) {
n = recv(sock, data, sizeof(data), 0);
if (strncmp("!EOF!", data, 5) == 0) {
break;
}
if (n <= 0) {
break;
return;
}
fwrite(data, sizeof(char), sizeof(data), fp);
bzero(data, sizeof(data));
}
fclose(fp);
return;
}
我终于在以下Post的帮助下弄明白了:
我重写了示例代码以满足我的需要。到目前为止效果很好。
感谢大家让我对这个主题有了更多的了解,并帮助我确定了我们在途中进行的必要检查!
这里对新代码进行简要说明:
首先需要认识到的是,像 send() recv() fread() fwrite() 这样的函数在传递之前可能不会完全填满它们的缓冲区。这意味着如果您有一个指定大小为 100 的缓冲区,它们可能只会将其填充到 89 95 或其他大小。因此,文件很可能已损坏。要解决此问题,需要检查每次调用 send() recv() fread() fwrite() 函数。
首先,您需要在服务器端和客户端都具备这两个功能。这些确保正在发送/接收整个缓冲区。 它基本上只是循环 send() / recv() 直到缓冲区被填满。
int RecvBuffer(int sock, char* buffer, int bufferSize, int chunkSize) {
int i = 0;
while (i < bufferSize) {
const int l = recv(sock, &buffer[i], __min(chunkSize, bufferSize - i), 0);
if (l < 0) { return l; }
i += l;
}
return i;
}
int SendBuffer(int sock, char* buffer, int bufferSize, int chunkSize) {
int i = 0;
while (i < bufferSize) {
const int l = send(sock, &buffer[i], __min(chunkSize, bufferSize - i), 0);
if (l < 0) { return l; }
i += l;
}
return i;
}
接下来,我们需要对下载/上传文件所调用的函数应用相同的检查。在这里,我循环遍历上述填充缓冲区的函数和 fread() fwrite(),直到所有字节 (fileSize) 都已发送。 chunkSize 参数定义发送的每个包的大小。到目前为止,我使用 65.536 (64kb) 没有任何问题。
int RecvFile(int sock, char *filePath, int chunkSize, int fileSize) {
char *lastSlash = strrchr(filePath, '\');
char *filename = lastSlash ? lastSlash +1 : filePath;
FILE *fp = fopen(filename, "wb");
char buffer[chunkSize];
int i = fileSize;
while (i != 0) {
const int r = RecvBuffer(sock, buffer, (int)__min(i, (int)chunkSize), chunkSize);
if ((r < 0) || !fwrite(buffer, sizeof(char), r, fp)) { break; }
i -= r;
}
bzero(buffer, sizeof(buffer));
fclose(fp);
printf("\n%s%s[+] Download Successful\n\n", KGRN, BGHT);
return -3;
}
int SendFile(int sock, char *fileName, int chunkSize, int fileSize) {
FILE *fp = fopen(fileName, "rb");
char buffer[chunkSize];
int i = fileSize;
while (i != 0) {
const int ssize = __min(i, (int)chunkSize);
if (!fread(buffer, sizeof(char), ssize, fp)) { break; }
const int l = SendBuffer(sock, buffer, (int)ssize, (int)chunkSize);
if (l < 0) { break; }
i -= l;
}
bzero(buffer, sizeof(buffer));
fclose(fp);
printf("\n%s%s[+] Upload Successful\n\n", KGRN, BGHT);
return -3;
}