你的发送代码存在许多逻辑错误:
缺乏足够的错误处理。
向send()
传递错误的缓冲区大小(提示:如果文件大小不是1024的整数倍,则最后一个缓冲区的大小不会为1024)。
假设send()
一次性发送整个缓冲区(提示:它很少这样做)。您需要循环调用send()
,直到整个缓冲区都被发送。
误解send()
的返回值(提示:它不返回布尔值)。它返回实际发送的字节数(也就是被接受到套接字内部缓冲区中以便在后台传输的字节数量)。
在每次send()
之后将错误的值添加到total
中,因为您假设send()
一次性发送整个缓冲区。
在文件末尾发送分隔符字符串,而无论该分隔符是否出现在发送的文件中。更安全的做法是在发送文件字节之前发送文件大小。
在发送分隔符字符串时指定了错误的缓冲区大小(提示:"Done"
不是1024字节大小)。
未关闭filewrite
句柄。您没有调用fclose()
关闭它。
因此,请尝试使用类似以下的代码:
BOOL SendRaw(const void *buffer, int size) {
const char *ptr = (const char*)buffer;
int numSent;
while (size > 0) {
numSent = send(s, ptr, size, 0);
if (numSent == -1)
return FALSE;
ptr += numSent;
size -= numSent;
}
return TRUE;
}
BOOL SendFile(const wchar_t* file) {
FILE* filewrite = fopen("test.txt", "a");
if (!filewrite)
return FALSE;
FILE* fp = _wfopen(file, L"rb");
if (!fp) {
fclose(filewrite);
return FALSE;
}
if (fseek(fp, 0, SEEK_END) != 0) {
fclose(fp);
fclose(filewrite);
return FALSE;
}
long size = ftell(fp);
if (size == -1L) {
fclose(fp);
fclose(filewrite);
return FALSE;
}
rewind(fp);
uint32_t tmp = htonl(size);
if (!SendRaw(&tmp, sizeof(tmp))) {
fclose(fp);
fclose(filewrite);
return FALSE;
}
unsigned char buffer[1024];
int numBytes, numSent, total = 0;
while (size > 0) {
numBytes = fread(buffer, 1, min(sizeof(buffer), size), fp);
if (numBytes < 1) {
fclose(fp);
fclose(filewrite);
return FALSE;
}
if (!SendRaw(buffer, numBytes)) {
fclose(fp);
fclose(filewrite);
return FALSE;
}
size -= numBytes;
total += numBytes;
fprintf(filewrite, "%d\n", total);
}
fclose(fp);
fclose(filewrite);
return TRUE;
}
import struct
def recv_file_from_client(conn):
f = open("torecv","wb")
data = conn.recv(4)
if not data:
print "Error recv"
return
size = struct.unpack("!I", data)[0]
while(size > 0):
data = conn.recv(min(1024, size))
if not data:
print "Error recv"
return
f.write(data)
size -= len(data)
f.close()
print "Done recv"
send()
的返回代码。一个大于0的值是传递到发送缓冲区的字节数,这可能少于您要发送的字节数。(在非阻塞模式下,甚至可以为0。)您需要增加缓冲指针并相应地减少要发送的字节数,并重试直到达到缓冲区的末尾。如果出现错误,则返回小于0(-1)的值。与fread
类似:您有readedChar
中的项目(字节)数量,这可能少于1024,但您总是尝试发送sizeof(buffer)
,因此您可能会发送未定义/旧数据从buffer
中。 - Bodo