我正在编写一个小程序来请求一个文件块,然后让另一个程序返回该文件的特定块。我可以使用最多大约555000字节的文件来使用它,但是在比这更大的任何事情上,我得到了不寻常的行为。
在我的循环中,我检查进度缓冲区,它是一个整数数组,以查看我是否有一个特定的文件块。如果我这样做,那么我不发送对该块的请求,但如果我不这样做,那么我从同行请求该块。我有一个链接列表,我移动,列表中的每个对等体都有一个与之关联的sockfd。所以,从某种意义上说,我“循环”了这些要求。一旦我把它们发出去,我就会等待消息进来。我不知道这是不是最好的方法,但它似乎是最自然的。
但是,对于较大的文件,它会在select调用时挂起。我不完全确定为什么。如果有人能够对此有所了解,或建议采取更好的方法,我很乐意听到它。
这是我的代码。我没有包含我调用的函数的代码,但我认为在这种情况下它不是必需的(它们是Beej的sendall和recvall函数的修改版本)。还值得一提的是,这是一个多线程应用程序(使用pthreads),但我没有使用任何共享变量。感谢您抽出宝贵时间阅读本文!
total = (number of chunks in the file)
my_peers = (linked list of peer structs containing sockfds, etc)
int i;
progress_buf = (array of ints, each representing a chunk in a file, 0 means we don't have the chunk)
while (1) {
/* Send out the chunk requests */
for(z= 0; z < total; z++) {
/* Circles through the peer list */
if (temp -> next != NULL) {
temp_next = temp->next;
} else {
temp_next = my_peers;
}
if (progress_buf[z] == 0) {
/* Request_blocks performs a send */
/* Need to deal with the "hanging bytes" chunk */
if (((z + 1) == total) && (remainder_chunk == 1)) {
check = request_blocks(temp, remainder, remainder_chunk, z);
} else {
check = request_blocks(temp, remainder, 0, z);
}
/* Bad send, remove peer from file descriptors and list */
if (check != 0 ) {
FD_CLR(check, &masterr);
remove_peer(&my_peers, temp->socket);
}
}
temp = temp_next;
}
read_fdss = masterr;
/* HANGS RIGHT HERE */
if (select(fdmax+1, &read_fdss, NULL, NULL, NULL) < 0) {
perror("select");
}
read_fdss = masterr;
int got_block;
/* Means we've received a block */
for(i = 4; i <= fdmax; i++) {
got_block = -1;
if (FD_ISSET(i, &read_fdss)) {
/* Performs a recv */
got_block = receive_block(i, filename_copy, progress_buf);
/* Update the progress buffer */
if (got_block > -1) {
remaining_blocks++;
if (remaining_blocks == total) goto finished;
/* Failure- remove the peer */
} else if (got_block == -2) {
close(i);
FD_CLR(i, &masterr);
remove_peer(&my_peers, i);
}
}
}
}
}