Необычное поведение select / sock stream поведение
Я пишу небольшую программу для запроса фрагмента файла, а затем другая программа возвращает этот конкретный фрагмент файла. Я могу заставить это работать, используя файлы размером до 555000 байт, но на чем-то большем, я получаю необычное поведение.
В моем цикле я проверяю буфер прогресса, который является массивом целых чисел, чтобы увидеть, есть ли у меня определенный фрагмент файла. Если я это сделаю, то я не отправляю запрос на этот чанк, но если я не делаю, то я запрашиваю чанк от сверстника. У меня есть связанный список, по которому я перемещаюсь, где с каждым пэром в списке связан sockfd. Так что, в некотором смысле, я "разбираю" запросы. После того, как я отправляю их, я жду поступления сообщений. Я не знаю, является ли это лучшим подходом, но он казался наиболее естественным.
Однако для файлов большего размера он зависает при вызове select. Я не совсем уверен, почему. Если кто-то может пролить свет на это или предложить лучший подход, я хотел бы услышать это.
Вот мой код Я не включил код для функций, которые я вызываю, но я не думаю, что это необходимо в этом случае (они являются модифицированными версиями функций sendall и recvall Beej). Также стоит упомянуть, что это в многопоточном приложении (с использованием 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);
}
}
}
}
}