ファイルのチャンクを要求する小さなプログラムを作成してから、別のプログラムにそのファイルの特定のチャンクを返させます。約 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);
}
}
}
}
}