2016-01-27 40 views
7

1) API for send here zwraca Result<usize>. Dlaczego ? W mojej głowie wysyłanie UDP jest całkowite lub żadne. Zwracana wartość wskazuje na to, że wysyłanie może się udać, ale wszystkie dane nie mogą być napisany kod, który sprawia, że ​​tak:UDP API w Rust

let mut bytes_written = 0; 
while bytes_written < data.len() { 
    bytes_written += match udp_socket.send_to(&data[bytes_written..]) { 
     Ok(bytes_tx) => bytes_tx, 
     Err(_) => break, 
    } 
} 

Ostatnio ktoś powiedział mi, że to jest zupełnie niepotrzebne. Ale nie rozumiem. Jeśli to prawda, dlaczego zamiast tego nie jest to zwrot, który jest również tym, czego się spodziewałem?

2) For reads chociaż rozumiem. Mogłem nadać mu bufor o rozmiarze 100 bajtów, ale datagram może mieć tylko 50 bajtów. Zasadniczo powinienem używać tylko read_buf[..size_read]. Tutaj moje pytanie brzmi: co się dzieje, jeśli rozmiar bufora wynosi 100, ale rozmiar datagramu wynosi 150 bajtów? Czy recv_from wypełni tylko 100 bajtów i zwróci Ok(100, some_peer_addr)? Czy jeśli ponownie przeczytam, wypełni on pozostałą część datagramu? Co jeśli kolejny datagram o wielkości 50 bajtów dotarł do mojego drugiego odczytu? Czy otrzymam pozostałe 50 bajtów po raz drugi i 50 bajtów nowego datagramu po raz trzeci lub ukończę 100 bajtów po raz drugi, który zawiera również nowy datagram? Lub będzie błąd i stracę pierwszy datagram w mojej początkowej lekturze i nigdy nie będę w stanie go odzyskać?

Odpowiedz

9

Odpowiedź na oba te pytania leży w dokumentacji odpowiednich funkcji gniazd BSD, sendto() i recvfrom(). Jeśli używasz jakiegoś systemu * nix (na przykład OS X lub Linux), możesz użyć man sendto i man recvfrom, aby go znaleźć.

1) sendto() strona podręcznika jest dość ogólnikowa; Windows Strona API jawnie mówi, że możliwe jest, aby wartość zwracana była mniejsza niż len. Zobacz także pytanie: this. Wygląda na to, że ten konkretny moment jest nieco niedostatecznie udokumentowany. Myślę, że prawdopodobnie można założyć, że wartość zwracana będzie zawsze równa len lub kodowi błędu. Problemy mogą się zdarzyć, jeśli długość danych przesłanych przez sendto() przekroczy rozmiar wewnętrznego bufora wewnątrz jądra systemu operacyjnego, ale wydaje się, że przynajmniej Windows zwróci błąd w tym przypadku.

2) recvfrom() strona człowiek jednoznacznie stwierdza, że ​​ta część datagramu, który nie pasuje do bufora zostaną odrzucone:

recvfrom function() zwraca długość wiadomości pisemnej do bufor wskazywany przez argument bufora. W przypadku gniazd opartych na wiadomości, takich jak SOCK_RAW, SOCK_DGRAM i SOCK_SEQPACKET, cała wiadomość zostanie odczytana w pojedynczej operacji . Jeśli wiadomość jest zbyt długa, aby zmieścić się w dostarczonym buforze, i MSG_PEEK nie są ustawione w argumencie flags, to nadmiarowe bajty muszą zostać odrzucone.

Więc tak, recv_from() wypełni dokładnie 100 bajtów, reszta zostanie odrzucona, a ponadto wzywa do recv_from() powróci nowych datagramów.

2

Jeśli jesteś dig down, to po prostu owijasz C sendto function. Ta funkcja zwraca liczbę wysłanych bajtów, więc Rust po prostu przekazuje ją dalej (podczas obsługi przypadku -1 i przełączania errno na rzeczywiste błędy).