C/C++通过套接字下载/上传文件



我目前正在尝试通过套接字(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 Filenn", 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 Successfulnn", 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;
}

在以下帖子的帮助下,我终于找到了答案:

通过TCP套接字C++发送文件|Windows

我重写了示例代码以满足我的需要。到目前为止效果不错。

感谢大家让我对这个话题有了更多的了解,并帮助我在途中进行必要的检查!

这里的新代码与简要解释:

首先需要认识到的是,像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;
}

接下来,我们需要在被调用来下载/上传文件的函数中应用相同的检查。在这里,我循环上面填充Buffer的函数和fred((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 Successfulnn", 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 Successfulnn", KGRN, BGHT);
return -3;
}

最新更新