České vysoké učení technické v Praze FAKULTA INFORMAČNÍCH TECHNOLOGIÍ katedra počítačových systémů Komunikace v sítích TCP/IP (2) Jiří Smítka jiri.smitka@fit.cvut.cz 25.2.2011 1/34
Opakování pojmů IP adresa maska sítě číslo sítě číslo počítače v síti brána (gateway) směrovač (router) přepínač (switch) 25.2.2011 2/34
Příklad: Jsou 2 IP adresy ve stejné síti? 83.1.66.222/18 X 83.1.63.1/18 25.2.2011 3/34
Příklad: Jsou 2 IP adresy ve stejné síti? 83.1.66.222/18 X 83.1.63.1/18 01010111 00000001 01000010 11011110 01010111 00000001 00111111 00000001 A co kdyby byla maska /17? 01010111 00000001 01000010 11011110 01010111 00000001 00111111 00000001 číslo sítě = 83.1.0.0/17 25.2.2011 4/34
Příklad: Supernet Spojte 2 sítě do jednoho supernetu tak, aby mělo číslo sítě co nejvíce bitů: 83.1.66.222/18 83.1.63.1/20 25.2.2011 5/34
Příklad: Supernet Spojte 2 sítě do jednoho supernetu tak, aby mělo číslo sítě co nejvíce bitů: 83.1.66.222/18 83.1.63.1/20 01010111 00000001 01000010 11011110 01010111 00000001 00111111 00000001 01010111 00000001 0xxxxxxx xxxxxxxx 83.1.0.0/17 25.2.2011 6/34
Příklad: Subnet Na jaké subnety s maskou /20 lze rozdělit supernet 83.1.64.0/18? 25.2.2011 7/34
Příklad: Subnet Na jaké subnety s maskou /20 lze rozdělit supernet 83.1.64.0/18? 01010111 00000001 01000000 00000000 01010111 00000001 01xx0000 00000000 83.1.64.0/20...01000000 00000000 83.1.80.0/20...01010000 00000000 83.1.96.0/20...01100000 00000000 83.1.112.0/20...01110000 00000000 25.2.2011 8/34
Příklad: Nejmenší možný rozsah adres Do sítě je zapojeno 7 počítačů. Jaká bude maska sítě, aby byl rozsah IP adres použitelných v této v síti co nejmenší? 25.2.2011 9/34
Příklad: Nejmenší možný rozsah adres Do sítě je zapojeno 7 počítačů. Jaká bude maska sítě, aby byl rozsah IP adres použitelných v této v síti co nejmenší? 00...0 (číslo sítě) xx...x 7 počítačů 11...1 (broadcast) celkem 9 adres 4 bity, tedy /28 25.2.2011 10/34
Příklad: Nejmenší možný rozsah adres Do sítě je zapojeno 7 počítačů. Jaká bude maska sítě, aby byl rozsah IP adres použitelných v této v síti co nejmenší? 00...0 (číslo sítě) 10.1.1.0 xx...x 7 počítačů 10.1.1.1 až.14 11...1 (broadcast) 10.1.1.15 celkem 9 adres 4 bity, tedy /28 25.2.2011 11/34
test 25.2.2011 12/34
Programové rozhraní BSD socketů 25.2.2011 13/34
Rozdíl mezi protokolem TCP a UDP TCP proud dat (stream) spolehlivý přenos dat odeslaná data zachovávají pořadí vyšší režie UDP jednotlivé datagramy datagram se může ztratit datagramy se mohou prohodit jednodušší protokol 25.2.2011 14/34
TCP neřeší message framing Vysílač write( Dinosaurus ); write( sežral ); write( přesličku. ); Přijímač read( Dino ); read( saurus sežra ); read( l přesličku ); read(. ); Jestliže vysílač zapíše do kanálu blok dat jedním zápisem, nemusí to nutně znamenat, že je přijímač přečte jedním voláním funkce read / recv. 25.2.2011 15/34
Programovací jazyk C: protokol TCP sockfd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP); bind( sockfd, &my_addr, sizeof(my_addr)); listen( sockfd, delka_fronty); connect( sockfd, (sockaddr *) &sin, sizeof(sin)); c_sockfd = accept( sockfd, &rem_addr, &rem_addr_len); musí být nastaveno na sizeof(rem_addr) len = recv( c_sockfd, buffer, BUFFERSIZE, 0); send( c_sockfd, buffer, len, 0); close( c_sockfd); close( sockfd); 25.2.2011 16/34
Programovací jazyk C: protokol TCP Klient s = socket() connect(s) write(s) read(s) close(s) Server s = socket() bind(s) listen(s) c = accept(s) recv(c) send(c) close(c) close(s) 25.2.2011 17/34
Programovací jazyk C: protokol UDP sockfd = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP); bind( sockfd, &my_addr, sizeof(my_addr)); sendto( sockfd, buffer, len, 0, &addr, sizeof(addr)); len = recvfrom( sockfd, buffer, BUFFERSIZE, 0, &rem_addr, &rem_addr_len); musí být nastaveno na sizeof(rem_addr) close( sockfd); 25.2.2011 18/34
Programovací jazyk C: protokol UDP Vysílač s = socket() bind(s) sendto(s) recvfrom(s) close(s) Přijímač s = socket() bind(s) recvfrom(s) sendto(s) close(s) 25.2.2011 19/34
java.net.socket BI-PSI - Počítačové sítě - proseminář Programovací jazyk Java: protokol TCP (1) konstruktory: Socket() Socket( String, int) Socket( InetAddress, int) metody: close() getinetaddress() getport() getlocalport() getinputstream() getoutputstream() set* 25.2.2011 20/34
Programovací jazyk Java: protokol TCP (2) java.net.serversocket konstruktory: ServerSocket() ServerSocket( int) metody: accept() bind( SocketAddress) close() getinetaddress() getlocalport() tostring() : 25.2.2011 21/34
Programovací jazyk Java: protokol TCP (3) Klient Server s = new Socket(h,p); ss = new ServerSocket(p); cs = ss.accept(); out = s.getoutputstream(); out = cs.getoutputstream(); in = cs.getinputstream(); in = s.getinputstream(); out.print('a'); in.read(); in.read(); out.print('b'); out.close(); out.close(); in.close(); in.close(); cs.close(); s.close(); ss.close(); 25.2.2011 22/34
Programovací jazyk Java: protokol UDP (1) java.net.datagramsocket konstruktory: DatagramSocket() DatagramSocket( int) metody: close() bind() getlocalport() getlocaladdress() receive( DatagramPacket) send( DatagramPacket) setsotimeout( int) : 25.2.2011 23/34
Programovací jazyk Java: protokol UDP (2) java.net.datagrampacket konstruktory: DatagramPacket( byte[], int) DatagramPacket( byte[], int, InetAddress, int) metody: InetAddress getaddress() getport() byte[] getdata() getlength() setdata( byte[]) setlength( int) : 25.2.2011 24/34
Programovací jazyk Java: protokol UDP (3) Vysílač s = new DatagramSocket(); p = new DatagramPacket(m,len,h,p); s.send(p); p = new DatagramPacket(m,len); s.receive(p); s.close(); Přijímač s = new DatagramSocket(p); p = new DatagramPacket(m,len); s.receive(p); length = p.getlength(); address = p.getaddress(); fromport = p.getport(); p = new DatagramPacket(m,len,h,p); s.send(p); s.close(); 25.2.2011 25/34
Špatně navržený TCP server Klient nemusí nic řešit (zavolá socket + connect + send/recv + close) Server by měl umět obsloužit více klientů. Lze ho napsat např. tak, že obsluhu dalšího klienta zahájí až po dokončení obsluhy předchozího klienta: while (...) { s = accept(...); recv(s) + send(s); close(s); } Jak dlouho by google vyřizoval požadavky, kdyby pracoval tímto způsobem? 25.2.2011 26/34
Méně špatně navržený TCP server Asi bude zapotřebí nějaké paralelizace (procesy, vlákna) Hlavní proces může volat accept a pro každého klienta vytvořit nový proces: while (...) { s = accept( ss,...); if (fork()) == 0) { close(ss); recv(s) + send(s); close(s); exit(); } } close(s); + klienty zpracovává paralelně - může být náročné na systémové zdroje - vytvořit proces / vlákno trvá hodně dlouho 25.2.2011 27/34
Dobře navržený TCP server (vlákna) Využívá pro každého klienta jedno vlákno / proces. Vlákna jsou předpřipravena a recyklována. c = accept(s) probudí vlákno a předá socket while (1) { Server se snaží udržovat N volných vláken. } while (1) suspend() { send(c) recv(c) : close(c) suspend() send(c) recv(c) : close(c) 25.2.2011 28/34 }
Dobře navržený TCP server (1 proces) Všechny operace se odehrávají v 1 procesu Základem je funkce select() = čekání na událost while (1) { select({s,c}); if event(s) { c[i] = accept(s); } for (j = 0..N) { if event(c[j]) { recv(c) / send(c) / close(c); } } } 25.2.2011 29/34
Použití funkce select() Java: java.nio.channels.selector Selector.select( timeout) Using a Selector to Manage Non-Blocking Sockets http://www.exampledepot.com/egs/java.nio/nbclient.html (25.2.2011) C: #include <sys/select.h> select( nfds, readfds, writefds, exceptfds, timeout); Podobně pracuje poll (je trochu jednodušší). 25.2.2011 30/34
Špatně navržený UDP server Jediný problém je neblokující čtení ze socketu. Možné řešení: Označím všechny sockety jako neblokující (setsockopt nebo přímo v recvfrom) a průběžně je kontroluji: while (...) { if (recvfrom(s1)!= 0) { } if (recvfrom(s1)!= 0) { } if (recvfrom(s1)!= 0) { } } - drasticky vytěžuje CPU 25.2.2011 31/34
Pořád ještě špatně navržený UDP server Abychom neblokovali CPU, vložíme sleep(): while (...) { if (recvfrom(s1)!= 0) { } if (recvfrom(s1)!= 0) { } if (recvfrom(s1)!= 0) { } sleep(100 ms) } + toto řešení již CPU nevytěžuje - klient ale může zbytečně čekat až 100 ms 25.2.2011 32/34
Dobře navržený UDP server Použijeme select(): while (...) { naplň fdset; select( fdset, timeout); if (timeout) { } else { foreach socket in fdset { if event(socket) { } } } Jediné správné řešení!!! } 25.2.2011 33/34
Nyní byste již měli zvládnout napsat obě programovací úlohy. 25.2.2011 34/34