我目前正在嘗試通過套接字(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;
}
uj5u.com熱心網友回復:
我終于在以下帖子的幫助下弄清楚了:
通過 TCP 套接字發送檔案 C | 視窗
我重寫了示例代碼以滿足我的需要。到目前為止,它就像一個魅力。
感謝大家讓我對這個話題有了更多的了解,并幫助我在途中進行必要的檢查!
這里新的代碼有一個簡短的解釋:
首先需要認識到的是,像 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;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/434930.html
