【发布时间】:2021-12-16 04:11:24
【问题描述】:
我想在我的 c 程序中通过套接字接收一个文件,为此我创建了一个函数 recvfile_all。它根据参数data 分块接收文件。
struct filedata 定义为
struct filedata {
struct stat st;
char filename[FILENAME_MAX];
};
我的函数的代码是-
// Receive a file based on filedata. Return the number of bytes
// left to receive in case of error
size_t recvfile_all(int sock, const struct filedata *data) {
size_t to_recv = data->st.st_size; // total data to receive for a file
size_t recv; // length of data to receive once
char *buffer = malloc(0); // buffer to hold chunk
size_t chunk_s = data->st.st_blksize; // chunk size to receive file in
size_t supp_to_recv;
FILE *file = fopen(data->filename, "w");
if (file == NULL) return to_recv;
while (to_recv) {
// receive a chunk if we have more to receive than the size of a
// single chunk, otherwise receive whatever is left
recv = to_recv > chunk_s ? chunk_s : to_recv;
supp_to_recv = recv;
buffer = realloc(buffer, recv);
recvall(sock, (char *)buffer, &recv);
if (recv < supp_to_recv)
return to_recv - recv; // return how much is left to receive
fwrite(buffer, 1, recv, file); // write what was received to file
to_recv -= recv;
}
fclose(file);
return to_recv;
}
函数recv_all 是一个类似于Beej 网络编程指南中的send_all 的函数。它只是从套接字接收一些字节。我已经对其进行了多次测试,并且运行良好,我认为此功能不存在错误。它被定义为-
int recvall(int s, char *buf, size_t *len) {
size_t total = 0; // how many bytes we've recveived
size_t bytesleft = *len; // how many we have left to receive
size_t n;
while (total < *len) {
n = recv(s, buf + total, bytesleft, 0);
if (n == -1 || n == 0) {
break;
}
total += n;
bytesleft -= n;
}
*len = total; // return number actually sent here
return n == -1 ? -1 : 0; // return -1 onm failure, 0 on success
}
我的功能似乎不起作用。任何想法为什么? 另外,错误肯定不在发送文件的代码中,我已经测试过多次了。
【问题讨论】:
-
如何它似乎不起作用?应该发生什么?实际发生了什么?当出现错误(在发送者或接收者中)时,您会打印出错误是什么?您是否使用调试器单步执行代码?实际发送的是什么?
-
@Someprogrammerdude 它接收到的垃圾数据混杂了一点点实际应该接收的数据,执行时没有错误
-
recv是否会返回-1或0?您是否尝试过在它发生时打印一些相关信息?以及如何检测“垃圾”数据?你实际上在发送什么?它是 binary 文件还是 text 文件? -
循环中的
realloc调用有什么用?为什么没有固定大小的缓冲区来接收数据?这应该会简化recvfile_all中的许多代码。更简单的代码意味着出现问题或错误的机会更少,同时也更容易调试。 -
recv不返回-1或0。我可以看到收到的数据是垃圾,因为它是一个文本文件。