[ Pobierz całość w formacie PDF ]
.Oznacza to, że od tego momentu możemy przystąpić do przesyłania danych mi ędzyprocesami.Do tego celu możemy wykorzystać szereg funkcji.Do dyspozycji mamy: read(), write(), recv(), send(),recvfrom(), sendto(), recvmsg(), sndmsg(), readv(), writev().Co prawda od przybytku głowa nie boli alespróbujemy trochę ograniczyć wybór.Funkcje recvfrom() i sendto() używane są głównie z gniazdkamibezpołączeniowymi.Natomiast recvmsg(), sndmsg(), readv() oraz writev() to różne specyficzne wariacje natemat podstawowych funkcji read(), write(), recv() oraz send() i nie będziemy się nimi zajmowali -zainteresowani mogą przejrzeć strony man'a dotyczące tych funkcji.W ten sposób zostały nam tylko czteryfunkcje.read()/write() zostały stworzone z myślą o plikach i chociaż nic nie stoi na przeszkodzie aby ich u żywaćw odniesieniu do gniazd to zaleca si ę korzystanie z pary recv()/send() gdyż funkcje te oferują możliwościspecyficzne dla operacji na gniazdach.Na placu boju pozostały teraz tylko dwie funkcje, które zaraz omówimynatomiast w dalszej części zapoznamy się jeszcze z recvfrom()/sendto() (gniazda bezpołączeniowe).Najpierw recv() (man 2 recv):s - Deskryptor gniazda, z którego chcemy odbierać dane (ten sam, który zwróciło wywołanie socket() iktóry podawaliśmy jako parametr dla connect()).buf - Wskaznik do bufora, w którym zostaną umieszczone55http://debian.esko.plodebrane dane.len - Wielkość wspomnianego bufora.flags - W tym właśnie parametrze uwidacznia się przewagafunkcji recv()/send() nad read()/write().Niektóre z możliwych wartości:MSG_OOB - Onacza chęć odebrania tzw.danych out-of-band.Trochę więcej na ten temat przy okazjiopisu funkcji send().MSG_PEEK - Powoduje odebranie danych z pocz ątku kolejki danych gotowych doodebrania ale bez usuwania odczytanej porcji danych z kolejki.To co ś w stylu preview ;).Następne wywołanierecv() odczyta więc te same dane.MSG_WAITALL - Jeśli ta flaga nie jest włączona to recv() odczytuje tyledanych z kolejki, ile jest aktualnie dost ępnych ale nie więcej niż każe parametr len.Zastanówmy się, co będziejeśli parametr len ustawiliśmy na 100 bajtów, a w kolejce do odebrania znajduje si ę tylko 50 bajtów.W takimprzypadku funkcja recv() wypełni podany bufor tylko 50 bajtami i je śli chcemy mieć pewność, że otrzymay całe100 bajtów to musimy wywoływać recv() kilkukrotnie aż do skutku.Właśnie aby ułatwić rozwiązanie takiegoproblemu możemy skorzystać z omawianej flagi.Spowoduje ona zablokowanie wywołania recv() do czasu ażcały zadeklarowany bufor zostanie wypełniony napływaj ącymi danymi.Flagi te można dodawać do siebie, np.MSG_PEEK | MSG_OOB.Funkcja recv() zwraca ilość bajtówodebranych albo -1 w przypadku błędu.Pora na send() (man 2 send):s - Deskryptor gniazda, przez które wysyłamy dane.msg - Wskaznik do bufora, który chcemy wysłać.len - Długość bufora.flags - Flagi.Niektóre z nich: MSG_OOB - Wysyła dane typu out-of-band.Połączenia strumieniowe(SOCK_STREAM) wydzielają dodatkowy logiczny kanał danych z głównego strumienia.Jest to wła śnie kanałprzeznaczony dla danych typu OOB.Infor macje z tegoż kanału logicznego odczytuje się przy użyciu funkcjirecv() z włączoną flagą MSG_OOB.MSG_DONTWAIT - Przełącza funkcję send() w tryb nieblokujący.Jeśliwysyłane dane nie mieszczą się w buforze danych oczekujących na wysłanie to funkcja zwróci błąd EAGAIN.Wprzypadku, gdy flaga ta nie jest wł ączona funkcja send() blokuje się do momentu aż wszystkie dane zostanąwysłane.send() zwraca ilość bajtów przekazanych do warstwy transportowej albo -1 (błąd).Wiemy już, jak utworzyć gniazdo, jak przesyłać za jego pośrednictwem dane, pozostało już tylkodowiedzieć się, jak zakończyć zainicjowane połączenie.Do tego celu można użyć dwóch funkcji:#includefd - Deskryptor gniazda skojarzonego z danym poł ączeniem.albo,s - Deskryptor gniazda.how - Może przyjmować trzy wartości:0 - Odbieranie danych nie będzie możliwe.W praktyce wygląda to tak, że jądro potwierdza zdalnemu procesowiodebranie poszczególnych segmentów ale dane w nich zawarte nie s ą umieszczane w buforze odbiorczym gniazdalokalnego.1 - Wysyłanie nie będzie możliwe.Proces lokalny sygnalizuje w ten sposób swojemu zdalnemu partnerowi, żewysłał już wszystko, co miał do wysłania.Na poziomie warstwy transportowej odpowiada to wysłaniu segmentuTCP z flagą FIN.2 - Zarówno wysyłanie, jak i odbieranie nie b ędzie możliwe.Odpowiednik close(s).56http://debian.esko.plWarto w tym miejscu podkreślić różnicę między wywołaniami close(s) oraz shutdown(s,2).T o pierwszespowoduje rzeczywiste zakończenie połączenia (czyli czterosegmentową sekwencję FIN/ACK) tylko jeśli licznikodniesień deskryptora gniazda jest równy 1.Licznik ten jednak mo że mieć większą wartość jeśli z jednegogniazda korzysta w tym samym czasie kilka procesów (np.rodzic i potomek).Z kolei wywołanie shutdown()natychmiast zamyka połączenie niezależnie od licznika odniesie ń.7.2.TCP: SOCK_STREAMPo przyswojeniu tych wszystkich wiadomości teoretycznych czas na sprawdzenie tego w praniu.Pierwszym programem, który napiszemy korzystaj ąc z dotychczasowej wiedzy o gniazdach b ędzie prosty klientusługi POP3 (ang.Post Office Protocol 3, protokół przesyłu poczty dla u żytkowników końcowych).Najpierw potrzebne pliki nagłówkowe:Teraz kilka makr, z których skorzystamy w programie
[ Pobierz całość w formacie PDF ]