Tryb bezpołączeniowy (datagramowy)

Podobne dokumenty
Klient-Serwer Komunikacja przy pomocy gniazd

Programowanie przy użyciu gniazdek

Iteracyjny serwer TCP i aplikacja UDP

Gniazda UDP. Bartłomiej Świercz. Łódź, 3 kwietnia Katedra Mikroelektroniki i Technik Informatycznych. Bartłomiej Świercz Gniazda UDP

Komunikacja sieciowa - interfejs gniazd

Literatura uzupełniająca: W. Richard Stevens, Programowanie zastosowań sieciowych w systemie Unix WNT 1998

Podstawowe typy serwerów

Programowanie Sieciowe 1

Gniazda BSD. komunikacja bezpołączeniowa

Programowanie współbieżne i rozproszone

PROTOKOŁY WARSTWY TRANSPORTOWEJ

Gniazda BSD. Procesy w środowisku sieciowym. Gniazda podstawowe funkcje dla serwera. Gniazda podstawowe funkcje dla klienta

Instytut Teleinformatyki

Gniazda surowe. Bartłomiej Świercz. Łódź,9maja2006. Katedra Mikroelektroniki i Technik Informatycznych. Bartłomiej Świercz Gniazda surowe

Komunikacja międzyprocesowa. Krzysztof Banaś Systemy rozproszone 1

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

5. Model komunikujących się procesów, komunikaty

Sieci komputerowe. Wykład 7: Transport: protokół TCP. Marcin Bieńkowski. Instytut Informatyki Uniwersytet Wrocławski

Programowanie sieciowe

ZESZYTY ETI ZESPOŁU SZKÓŁ W TARNOBRZEGU Nr 1 Seria: Teleinformatyka 2013

Architektura typu klient serwer: przesyłanie pliku tekstowo oraz logowania do serwera za pomocą szyfrowanego hasła

Oprogramowanie komunikacyjne dla Internetu rzeczy Laboratorium nr 4 komunikacja unicastowa IPv6

76.Struktura oprogramowania rozproszonego.

Mechanizmy pracy równoległej. Jarosław Kuchta

2. Interfejs gniazd Gniazdo

Programowanie aplikacji równoległych i rozproszonych. Wykład 4

Aplikacja Sieciowa. Najpierw tworzymy nowy projekt, tym razem pracować będziemy w konsoli, a zatem: File->New- >Project

Gniazda - Wstęp. Oprogramowanie systemów równoległych i rozproszonych. Sposób komunikacji. Domena adresowa. olas@icis.pcz.pl

Transport. część 2: protokół TCP. Sieci komputerowe. Wykład 6. Marcin Bieńkowski

IPC: Kolejki komunikatów

Transport. część 2: protokół TCP. Sieci komputerowe. Wykład 6. Marcin Bieńkowski

Gniazda BSD implementacja w C#

Warstwa transportowa. Warstwa transportowa. Enkapsulacja. Zapewnienie niezawodnego przesyłania danych /wg ISO/ Transmisja bezpołączeniowa

Projektowanie oprogramowania systemów KOMUNIKACJA SIECIOWA I SYSTEMY RPC

Architektura typu klient serwer: uproszczony klient POP3

Kolejki FIFO (łącza nazwane)

Sieci komputerowe. Wykład 5: Warstwa transportowa: TCP i UDP. Marcin Bieńkowski. Instytut Informatyki Uniwersytet Wrocławski

TCP - receive buffer (queue), send buffer (queue)

Tryby komunikacji między procesami w standardzie Message Passing Interface. Piotr Stasiak Krzysztof Materla

MODEL WARSTWOWY PROTOKOŁY TCP/IP

Sieci komputerowe 1 DSRG

Komunikacja z wykorzystaniem Protokołu TCP oraz funkcji AG_SEND/AG_RECV

Politechnika Łódzka. Instytut Systemów Inżynierii Elektrycznej

Opis protokołu RPC. Grzegorz Maj nr indeksu:

Przesyłania danych przez protokół TCP/IP

Protokoły sieciowe - TCP/IP

Systemy operacyjne System sieciowy UNIX-a

3. Identyfikacja. SKŁADNIA #include <sys/socket.h> int getpeername(int socket, struct sockaddr *addr, int *addrlen);

Akademia Techniczno-Humanistyczna w Bielsku-Białej

Programowanie równoległe i rozproszone. Praca zbiorowa pod redakcją Andrzeja Karbowskiego i Ewy Niewiadomskiej-Szynkiewicz

Sieci komputerowe. Zajęcia 3 c.d. Warstwa transportu, protokoły UDP, ICMP

Od uczestników szkolenia wymagana jest umiejętność programowania w języku C oraz podstawowa znajomość obsługi systemu Linux.

Systemy rozproszone. Krzysztof Banaś Obliczenia równoległe 1

Gniazda. S. Samolej: Gniazda 1

Zdalne wywołanie procedur. Krzysztof Banaś Systemy rozproszone 1

Programowanie Równoległe Wykład 4. MPI - Message Passing Interface. Maciej Matyka Instytut Fizyki Teoretycznej

Zadanie 2: transakcyjny protokół SKJ (2015)

1. Model klient-serwer

RPC. Zdalne wywoływanie procedur (ang. Remote Procedure Calls )

Aplikacja Sieciowa wątki po stronie klienta

SEGMENT TCP CZ. II. Suma kontrolna (ang. Checksum) liczona dla danych jak i nagłówka, weryfikowana po stronie odbiorczej

Programowanie w modelu przesyłania komunikatów specyfikacja MPI. Krzysztof Banaś Obliczenia równoległe 1

Stos protokołów TCP/IP (ang. Transmission Control Protocol/Internet Protocol)

TCP/IP formaty ramek, datagramów, pakietów...

Dr Michał Tanaś(

1. Model klient-serwer

Dokumentacja wstępna TIN. Rozproszone repozytorium oparte o WebDAV

Pliki. Funkcje tworzące pliki i operujące na nich opisane są w części 2 pomocy systemowej. Tworzenie i otwieranie plików:

Komunikacja międzyprocesowa. Krzysztof Banaś Systemy rozproszone 1

Wykład 4: Protokoły TCP/UDP i usługi sieciowe. A. Kisiel,Protokoły TCP/UDP i usługi sieciowe

Podstawy Transmisji Danych. Wykład IV. Protokół IPV4. Sieci WAN to połączenia pomiędzy sieciami LAN

Protokoły zdalnego logowania Telnet i SSH

Od uczestników szkolenia wymagana jest umiejętność programowania w języku C oraz podstawowa znajomość obsługi systemu Windows.

socket(int domain, int type, int protocol)

61 Topologie wirtualne

Skąd dostać adres? Metody uzyskiwania adresów IP. Statycznie RARP. Część sieciowa. Część hosta

Instrukcje dotyczące funkcji zarządzania pasmem w urządzeniach serii ZyWALL.

Instalacja programu Ozon.

Tunelowanie, kapsułkowanie, XDR. 1. Transmisja tunelowa i kapsułkowanie serwery proxy. 2. Zewnętrzna reprezentacja danych XDR.

Sieci komputerowe - Protokoły warstwy transportowej

Enkapsulacja RARP DANE TYP PREAMBUŁA SFD ADRES DOCELOWY ADRES ŹRÓDŁOWY TYP SUMA KONTROLNA 2 B 2 B 1 B 1 B 2 B N B N B N B N B Typ: 0x0835 Ramka RARP T

Programowanie sieciowe

Referencyjny model OSI. 3 listopada 2014 Mirosław Juszczak 37

Ćwiczenie nr: 9 Obliczenia rozproszone MPI

AKADEMIA GÓRNICZO-HUTNICZA. Wydział Elektrotechniki, Automatyki, Informatyki i Elektroniki KATEDRA INFORMATYKI. SyncFile

Architektury systemów rozproszonych LABORATORIUM. Ćwiczenie 1

Sieci komputerowe Warstwa transportowa

Adresowanie grupowe. Bartłomiej Świercz. Katedra Mikroelektroniki i Technik Informatycznych. Łódź, 25 kwietnia 2006

ZiMSK dr inż. Łukasz Sturgulewski, DHCP

Podstawowe protokoły transportowe stosowane w sieciach IP cz.1

Gniazda BSD UNIWERSYTET GDAŃSKI WYDZIAŁ MATEMATYKI I FIZYKI. Jacek Nowicki

Programowanie Programowanie z użyciem gniazd

Tytuł: Instrukcja obsługi Modułu Komunikacji internetowej MKi-sm TK / 3001 / 016 / 002. Wersja wykonania : wersja oprogramowania v.1.

Serwer współbieżny połączeniowy

Komunikacja Master-Slave w protokole PROFIBUS DP pomiędzy S7-300/S7-400

TRX API opis funkcji interfejsu

Mechanizmy z grupy IPC

SUMA KONTROLNA (icmp_cksum) NUMER KOLEJNY (icmp_seq)

Wyjście do drukarki Centronix

Ćwiczenie nr: 9 Obliczenia rozproszone MPI

Transkrypt:

Tutaj trochę szerzej opisałam mechanizm gniazdek. 3 tematy wymienione poniŝej przeplatają się ze sobą więc wrzuciłam je do jednego worka i przedstawiłam w takim porządku, który wydawał mi się najbardziej logiczny W wersji skróconej te pytania są juŝ zebrane po kolei tak jak G przykazał w tematach;) Miłej lektury *41. Schemat funkcjonowania mechanizmu gniazdek. + *42. Elementy i ograniczenia przesyłania bezpołączeniowego za pomocą gniazdek. + *43. Elementy i właściwości przesyłania połączeniowego za pomocą gniazdek. I.Cel Komunikacja pomiędzy procesami działającymi w róŝnych węzłach sieci wymaga, aby jeden z tych procesów czekał w gotowości do odebrania danych (nasłuchiwał), wówczas drugi proces moŝe skomunikować się z nim w dowolnym, wybranym przez siebie w momencie. W związku z takim modelem komunikacji proces nasłuchujący nazywany jest serwerem, a proces komunikujący się z nim i korzystający z jego usług nazywany jest klientem. Klient musi zatem znać adres serwera przed nawiązaniem komunikacji, serwer natomiast nie wie jacy klienci się do niego zgłoszą, ich adresy moŝe więc poznać dopiero po nawiązaniu komunikacji. II.Wstęp Gniazda BSD umoŝliwiają komunikację sieciową (między procesami działającymi na róŝnych komputerkach )z wykorzystaniem róŝnych rodzin protokołów np. TCP/IP, IPX, AppleTalk i wielu innych. Zdecydowanie najpopularniejsza jest obecnie komunikacja w dziedzinie Internetu, wykorzystująca protokoły TCP/IP. Gniazda dają równieŝ moŝliwość komunikacji międzyprocesowej w dziedzinie UNIX-a, czyli wewnątrz jednego systemu operacyjnego z wykorzystaniem jego wewnętrznych protokołów. III.Rodzaje transmisji Funkcje systemowe interfejsu gniazd pozwalają zrealizować transmisję danych w protokole połączeniowym lub bezpołączeniowym (rozstrzygniecie w momencie tworzenia gniazdka.). PoniŜej przedstawiłam typowe scenariusze takich transmisji.

Tryb bezpołączeniowy (datagramowy) Tryb połączeniowy tryb połączeniowy, obsługiwany przez protokół TCP/IP, gwarantujący przesyłanie danych w postaci strumienia, w sposób niezawodny (bez utraty danych), bez duplikowania danych i bez zmiany ich kolejności, w obu kierunkach (od serwera do klienta i od klienta do serwera), Główne właściwości: nawiązanie połączenia asymetryczne, później wymiana danych symetryczna, do funkcji nie trzeba przekazywać adresów(są one ustalane podczas nawiązywania połączenia) tryb bezpołączeniowy, obsługiwany przez protokół UDP/IP, umoŝliwiający przesyłanie datagramów, czyli określonych porcji danych, nie gwarantujący niezawodnego doręczenia, dopuszczający duplikację całego datagramu lub zmianę kolejności doręczenia dwóch kolejno wysłanych datagramów. Główne ograniczenia: tego trybu: wykorzystywany protokół UDP, kontrola poprawności naleŝy do aplikacji, ograniczony rozmiar porcji danych limitowany własnościami protokołu i sieci. IV. Operacje na gniazdkach /* W tym dziale opiszę wszystkie funkcje wymienione na rysunkach, zarówno dla trybu połączeniowego jak i bezpołączeniowego poniewaŝ imho taki ciąg będzie bardziej logiczny (omówienie funkcji send() oraz sentdo() jednocześnie), w części skróconej zmienię trochę porządek tak aby odpowiadał ściśle na pytania z zestawu, które odnoszą się do dwóch trybów oddzielnie. */ 0.Reprezentacja w systemie (To juŝ zamieściłam w ramach ciekawostki dla wnikliwych )

Dla procesu w systemie Unix gniazdo jest rodzajem pliku specjalnego, w związku z czym moŝna wykonywać na jego deskryptorze podobne operacje, jak na pliku (read(), write(), close()). Zapis do gniazda lub odczyt z niego oznacza odpowiednio wysłanie lub odbiór danych przez sieć. 1. Utworzenie i otworzenie gniazda oraz otrzymanie jego deskryptora umoŝliwia funkcja systemowa socket(). KaŜdy z dwóch komunikujących się ze sobą procesów musi mieć własne gniazdo, które moŝe słuŝyć zarówno do wysyłania jak i odbioru danych. Tworząc gniazdo funkcją socket(), naleŝy wyspecyfikować tryb komunikacji (połączeniowy lub bezpołączeniowy), z którego wynika protokół transmisji danych przez to gniazdo (TCP lub UDP). Protokół jest równieŝ elementem wyróŝniającym gniazdo, czyli dwa gniazda o tym samym adresie ale róŝnych protokołach są róŝnymi gniazdami. int socket(int addrfamily, int sockettype, int protocol); - addrfamily - nazwa dziedziny (rodziny protokołów), forma adresowa + AF_INET, AF_UNIX - sockettype - sposób przesyłania danych, typ komunikacji np. + SOCK_STREAM - połączeniowy, + SOCK_DGRAM - bezpołączeniowy, - protocol protokół uŝywany przez gniazdko + IPPROTO_TCP, + IPPROTO_UDP + jesli 0 domyslny dla formy adresowej i typukomunikacji - return :int Funkcja zwraca deskryptor utworzonego gniazda (pliku) lub -1 w wypadku błędu. 2. Przydzielanie adresu W celu wysłania danych przez gniazdo musi zostać określony adresat, czyli gniazdo, do którego dane zostaną wysłane. Właściwy adres gniazda składa się z dwóch elementów: adresu węzła i numeru portu. KaŜde gniazdo musi mieć przydzielony lokalny adres zanim będzie mogło być uŝyte do komunikacji. Operację tę określa się równieŝ jako związywanie adresu z gniazdem lub nazywanie gniazda. Ostatnie określenie ma szczególne uzasadnienie w przypadku gniazd w dziedzinie UNIX-a, dla których adresami są nazwy ścieŝkowe plików. Pliki te są tworzone przez jądro podczas nazywania gniazda. Adres moŝe być przydzielony jawnie za pomocą funkcji bind() lub automatycznie przez jądro systemu. Funkcja ta musi być wywołana przez serwer zarówno w trybie połączeniowym jak i bezpołączeniowym int bind(socket socket, const struct sockaddr *myaddr,int addrlen); - socket deskryptor gniazda, utworzony przez funkcję socket(), - myaddr wskaźnik do struktury zawierającej adres własny - addrlen rozmiar struktury zawierającej adres Zamiast wskaźnika na strukturę sockaddr przekazuje się najczęściej wskaźnik na strukturę odpowiednią do rodziny aktualnie uŝywanych protokołów, wykonując przy przekazaniu wskaźnika rzutowanie typu na (struct sockaddr*). W dziedzinie Internetu uŝywa się struktury sockaddr_in o następującej definicji: struct sockaddr_in { sa_family_t sin_family; /* AF_INET */ u_init_16 sin_port; /* numer portu */ struct in_addr sin_addr; /* 32-bitowy adres węzła */

} char sin_zero[8]; /* nie uŝywane */ Struktura in_addr zawiera jedno pole typu long: struct in_addr{ u_int32_t s_addr; /* 32-bitowy adres właściwy węzła lub INADDR_ANY */ } 3.Ustanawianie połączenia : connect(), listen() akcept() a) Funkcja connect() uŝywana jest najczęściej przez klienta w trybie połączeniowym i słuŝy do zgłaszania Ŝądania nawiązania połączenia z serwerem. Przez wywołanie funkcji connect() gniazdu klienta przypisywany jest adres wybrany przez system. Proces klienta jest blokowany do momentu ustanowienia połączenia(funkcja czeka na potwierdzenie). Klient połączeniowy moŝe zrealizować tylko jedno pomyślne połączenie. int connect(socket socket, const struct sockaddr *servaddr, int addrlen); - socket - deskryptor gniazda, utworzony przez funkcję socket(), - servaddr - wskaźnik do struktury zawierającej adres serwera (struktura ta moŝe być róŝna dla róŝnych rodzin protokołów), - addrlen - rozmiar struktury zawierającej adres. b) Funkcja systemowa listen() Serwer protokołu połączeniowego wywołuje funkcję listen(), aby zgłosić w systemie gotowość przyjmowania połączeń i ustalić jednocześnie maksymalną liczbę połączeń oczekujących na obsłuŝenie. int listen(socket socket, int backlog); - socket - deskryptor gniazda, utworzony przez funkcję socket(), - backlog - parametr określający maksymalną liczbę Ŝądań oczekujących w kolejce na wykonanie funkcji accept(). c) Funkcja systemowa accept() Funkcja accept() wywoływana jest przez serwer w celu przyjęcia Ŝądania nawiązania połączenia, zgłoszonego wcześniej i oczekującego w kolejce. JeŜeli Ŝadne Ŝądanie nie dotarło, serwer jest blokowany do momentu otrzymania Ŝądania (funkcja czeka na Ŝądanie ). Po przyjęciu Ŝądania funkcja pod adres addr. wpisuje adres klienta i informuje aplikację, który klient został podłączony. Tworzy nowy deskryptor dla danego gniazda socket, który moŝe być następnie wykorzystywany przez proces obsługi zgłoszenia. Stare gniazdko nadal czeka na kolejne Ŝądania. (w zaleŝności od parametru funkcji listen()) SOCKET accept(socket socket, struct sockaddr * addr, int *addrlen); - socket - deskryptor gniazda, utworzony przez funkcję socket(), - addr - wskaźnik do struktury zawierającej adres klienta (struktura ta moŝe być róŝna dla róŝnych rodzin protokołów), - addrlen - rozmiar struktury zawierającej adres. 4.Przesyłanie danych

Sposób przesyłania danych jest uzaleŝniony od typu gniazd. Gniazda strumieniowe, wykorzystywane w transmisji połączeniowej, mogą być dostępne za pomocą typowych funkcji systemowych interfejsu plików. Po ustanowieniu połączenia, obydwa procesy uczestniczące w komunikacji znają juŝ swoje adresy i mogą korzystać z funkcji read() i write() lub recv() i send() do odbierania i wysyłania danych przez gniazdo. W pozostałych przypadkach, przesłanie i odbieranie datagramu wymaga podania adresu odbiorcy, co umoŝliwiają funkcje sendto() recvfrom(). a)funkcje systemowe send() i sendto() Działanie tych funkcji jest podobne do działania funkcji write() moŝna jednak w dodatkowym polu flags przekazać pewne opcje związane z wysłaniem komunikatu. Ponadto funkcja sendto() umoŝliwia podanie adresu docelowego w przypadku komunikacji bezpołączeniowej. int send(socket socket, const char *buf, int nbytes, int flags); int sendto(socket socket, const char *buf, int nbytes, int flags, const struct sockaddr *toaddr, int addrlen); - socket - deskryptor gniazda, utworzony przez funkcję socket() lub accept(), - buf - adres (wskaźnik) bufora, zawierającego dane do wysłania, - nbytes - liczba bajtów do wysłania, znajdująca się w buforze, - flags - znaczniki: - toaddr - wskaznik na strukture odpowiadajaca własciwej formie adresowej(adres odbiorcy), - addrlen - rozmiar struktury zawierającej adres. b) Funkcje systemowe recv() i recvfrom() Działanie tych funkcji jest podobne do działania funkcji read() moŝna jednak w dodatkowym polu flags przekazać pewne opcje związane z dobieraniem komunikatu. Ponadto funkcja recvfrom() umoŝliwia uzyskanie adresu nadawcy w przypadku komunikacji bezpołączeniowej. int recv(socket socket, char *buf, int nbytes, int flags); int recvfrom(socket socket, char *buf, int nbytes, int flags, struct sockaddr *fromaddr, int *addrlen); - socket - deskryptor gniazda, utworzony przez funkcję socket() lub accept(), - buf - adres (wskaźnik) bufora, który będzie zawierał dane po ich odebraniu,(pierwszy pakiet z kolejki) - nbytes - rozmiar bufora (maksymalna liczba bajtów, którą moŝna jednorazowo odebrać pozostałe dane >nbytes są tracone.) - flags - znaczniki: - fromaddr - wskaźnik do struktury, w której zapisany zostanie adres nadawcy danych. - addrlen - wskaźnik do zmiennej, przez którą zwrócony zostanie rozmiar struktury zawierającej adres. V LINKI Materiały z których korzystałam tworząc ten opis: (UWAGA deklaracje funkcji mogą się nieco róŝnić od tych podanych na wykładach np. zamiast argumentu : const struct blabla występuje struct blabla brakuje klucza : const) http://www.cs.put.poznan.pl/mszychowiak/dydaktyka/socketapi.html

http://www.imio.pw.edu.pl/vlsi/teaching/soe/materialy/lekcja10/ *44. Elementy i implementacje standardu MPI. 1 Interfejs MPI - Message Passing Interface (Interfejs Transmisji Wiadomości) standard interfejsu do przesyłania komunikatów w rzeczywistych i wirtualnych maszynach równoległych z pamiecia rozproszona (DM). - Biblioteka procedur i funkcji wywoływanych z programów napisanych w jezykach Fortran, C/C++ słuŝących do obsługi komunikatów i synchronizacji zadan wykonujacych najczesciej ten sam program. - Transfer danych pomiędzy poszczególnymi procesami programu wykonywanymi na procesorach maszyn będących węzłami klastra odbywa się za pośrednictwem sieci. - Program w MPI składa się z niezaleŝnych procesów operujących na róŝnych danych (MIMD). KaŜdy proces wykonuje się we własnej przestrzeni adresowej, aczkolwiek wykorzystanie pamięci współdzielonej teŝ jest moŝliwe. - Procesy są identyfikowane poprzez ich numer w grupie w zakresie 0.. groupsize - 1. 2 Implementacje MPI - Pierwszy standard MPI nazwany później MPI-1 był gotowy w maju 1994 roku - Drugi standard zwany MPI-2 ukończono w 1998 roku. Nie cieszył się on duŝą popularnością, poniewaŝ rok wcześniej opracowano MPICH, w którym zaimplementowano część poprawek wprowadzanych w MPI-2. - MPICH i LAM MPI to najczęściej stosowane implementacje standardu MPI. - W standardzie MPI-2 zdefiniowano równoległe operacje wejścia/wyjścia, które pierwotnie zostały zawarte w pakiecie MPI-IO rozwijanym specjalnie na potrzeby NASA, a następnie zmodyfikowane i przeniesione do nowego MPI-2. - Implementacje producentów sprzętu SA optymalizowane pod katem sprzętowych rozwiązań (sieci) komunikacyjnych i architektury (topologii) danego systemu. *45. Sposoby wywołania funkcji MPI. Prawie wszystkie funkcje MPI zwracają kod błędu: w C jako wartość funkcji, w Fortranie jako wartość ostatniego argumentu. Przed zwróceniem wartości wywoływana jest bieŝąca procedura obsługi błędu: standardowo powoduje przerwanie zadania, ustawienie uchwytu MPI_ERRORS_RETURN spowoduje zwracanie kodu błędu. MPI nie gwarantuje dalszego działania. W razie powodzenia zwracany jest MPI_SUCCESS Include Postac bibliotek załączanych dla języka: C : #include ``mpi.h`` Fortran : include `mpif.h` Format funkcji MPI C: int error; error = MPI_Xxxxx(parametr,...); MPI_Xxxxx(parametr,...); Fortran: INTEGER IERROR CALL MPI_XXXXX(parametr,..., IERROR) Przykład : Inicjacja biblioteki MPI Funkcja MPI_Init: ////////////////////////// C //////////////////////

int error = MPI_Init(int *argc, char **argv[]) c /////////Fortran INTEGER ierror CALL MPI_INIT(ierror) jak większość funkcji MPI zwraca stała int o wartości MPI_SUCCESS w przypadku pomyślnego wykonania. Wersja Fortran zwraca tylko argument ierror.