Когда вы имеете дело с несколькими сокетами, которые могут потенциально блокировать (в вашем случае чтение сокетов), вам необходимо определить, в каких сокетах есть данные, ожидающие чтения. Вы можете сделать это, вызвав select () и добавив сокеты в ваш read_set.
Для вашего сокета прослушивания, если вы вызываете accept () и нет ожидающего соединения, тогда ваш accept будет блокироваться до тех пор, пока не будет установлено новое соединение. Таким образом, вы также хотите выбрать () этот сокет. Как только вы примете этот клиент, вы захотите добавить его в свой read_set.
например. Псевдо-код
for (;;) {
struct timeval tv = { timeout, 0 };
fd_set read_set;
FD_ZERO(&read_set);
FD_SET(listen_sock, &read_set);
max_fd = max(max_fd, listen_sock);
/* add all your other other client sockets to thread read_set */
n = select(max_fd, &read_set, NULL, NULL, tv);
if (n > 0) {
if (FD_ISSET(listen_sock, &read_set)) {
cli = accept(listen_sock);
/* add to list of clients */
}
else {
for (int i = 0; i < max_clients; i++) {
if (FD_ISSET(clients[i], &read_set)) {
/* data is waiting. recv */
bytes = recv(clients[i], ..)
if (bytes <= 0) {
/* error or EOF, remove client list, so we don't select on this anymore */
}
}
}
}
}
Обратите внимание, что отправка также может блокироваться, если другой конец не читает активно, а буфер отправки заполнен. Поэтому, если вы отправляете, вы можете проверить, является ли он «отправляемым».