Pracuję na systemie Linux (serwer Ubuntu 7.04 z kernelem 2.6.20).wybór na gnieździe UDP nie kończy się, gdy gniazdo jest zamknięte - co robię źle?
Mam program, który ma wątek (wątek1) czeka na wybór dla gniazda UDP, aby stać się czytelne. Używam select (z moim gniazdem jako single readfd i single exceptfd) zamiast tylko wywoływać recvfrom, ponieważ chcę timeout.
Z innego wątku wyłączam i zamykam gniazdo. Jeśli zrobię to, podczas gdy wątek1 zostanie zablokowany w recvfrom, to recvfrom natychmiast się zakończy. Jeśli zrobię to, gdy wątek1 zostanie zablokowany w wybranym z limitem czasu, to wybór NIE zakończy się natychmiastowo, ale ostatecznie upłynie poprawnie.
Czy ktoś może mi powiedzieć, dlaczego zaznaczenie nie kończy się, gdy gniazdo jest zamknięte? Czy to nie wyjątek? Widzę, gdzie jest to nieczytelne (oczywiście), ale jest zamknięte, co wydaje się być wyjątkowe.
Oto otwarcie gniazda (wszystkie obsługi błędów usunięte zachować rzeczy proste):
m_sockfd = socket(PF_INET, SOCK_DGRAM, 0);
struct sockaddr_in si_me;
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(port);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(m_sockfd, (struct sockaddr *)(&si_me), sizeof(si_me)) < 0)
{
// deal with error
}
Oto SELECT że thread1 wykonuje:
struct timeval to;
to.tv_sec = timeout_ms/1000;// just the seconds portion
to.tv_usec = (timeout_ms%1000)*1000;// just the milliseconds
// converted to microseconds
// watch our one fd for readability or
// exceptions.
fd_set readfds, exceptfds;
FD_ZERO(&readfds);
FD_SET(m_sockfd, &readfds);
FD_ZERO(&exceptfds);
FD_SET(m_sockfd, &exceptfds);
int nsel = select(m_sockfd+1, &readfds, NULL, &exceptfds, &to);
UPDATE: Oczywiście (jak nizej), zamknięcie gniazda nie jest wyjątkowym warunkiem (z punktu widzenia wyboru). Myślę, że muszę wiedzieć: dlaczego? I czy to jest zamierzone?
NAPRAWDĘ chcę zrozumieć sposób, w jaki kryje się to wybrane zachowanie, ponieważ wydaje się sprzeczny z moimi oczekiwaniami. Tak więc, oczywiście muszę dostosować moje myślenie o tym, jak działa stos TCP. Proszę mi to wyjaśnić.
To byłoby dobre rozwiązanie. Niech wybrane czekaj zarówno na gniazdo, jak i potok, a drugi wątek zapisze w potoku, aby spowodować powrót do wyboru. –
To by działało i prawdopodobnie będzie tym, z czym skończę. Chciałem tylko uniknąć dodatkowych ruchomych części. Dzięki! –