Datakommunikation och Internet Socketprogrammering Peter Sundqvist Socket-programmering Klient/server ansatsen TCP/IP protokollgrafen Java-programering UDP TCP Korta tips om Strömmar Script Trådar (föreläsning 5) Programmering för distribution Varför datornät? För att distribuera beräkningar (i vid mening) distribuerade system För att dela på (exklusiva) resurser, tillhandahålla tjänster file server, mail server, databaser, videoserver, För att kommunicera mail, ftp, chat, cscw,... 1
Nätverks-applikationer Terminilogi En process är ett program som körs på en maskin (host). Inom samma maskin kan två processer kommunicera via interprocess communication definierat av OS. Signals, pipes, FIFO, shared memory, (sockets), etc Processer som kör på olika maskiner kommunicerar via application-layer protocols HTTP, FTP, etc User agent kallas ett gränssnitt mellan användaren och nätverksapplikationen. Web: Webläsare E-post: E-post-hanterare Strömmad film/ljud: Mediaspelare Applikationer och applikations-lagrets protokoll Applikation: kommunicerande, distruberade processer Körs på en maskin i ett nätverk, User space Utbyt meddelanden för att implementera applikationen som helhet E-port, fil-överföring, Web Applikations-lagerts protokoll En del av en applikation Definierar vilka meddelanden som skickas & dess funktion Använder nedre lagrets tjänster application transport network data link physical application transport network data link physical application transport network data link physical Klient - Server Paradigmen Klient: Tar kontakt med servern, pratar först Frågar typiskt efter en tjänst av servern. e.g. Web: Webläsaren är klient. E-post: E-posthanteraren är klient. Server: Förser klienten med den efterfrågade tjänsten e.g. Web-servern skickar efterfrågad Web-sida, E-post-server levererar brev application transport network data link physical request reply application transport network data link physical Typisk nätverk-app har två delar: klient och server 2
Klient/server ansatsen En server tillhandahåller en tjänst, en resurs Väntar på att någon behöver tjänsten En klient utnyttjar en tjänst Kontaktar en server och ber om en tjänst Servern är autonom och kan vägra att acceptera en klients begäran Klient/server ansatsen (forts) Dialogen mellan klient och server måste följa ett väl specificerat protokoll En server kan arbeta mot en förutbestämd kundkrets - är en del av en distribuerad applikation, eller ha en allmän uppgift - är en del av ett distribuerat system Applikationer Vilket underliggande transportprotokoll som används styrs av typen av applikation FINGER Web radio RLOGIN RPC FTP SMTP UDP TCP IP 3
TCP/IP - protokollstacken Applikationslagret HTTP, SMTP, Transportlagret UDP, TCP Nätverkslagret IP (version 4/6), ICMP, IPSec Länklagret Ethernet, token ring, GPRS, WLAN Fysiska lagret Kablarna... Applikation UDP TCP IP Kopplingsnivån Fysiska nivån UDP - User Datagram Protocol Best-effort - protokoll IP + portar + checksumma Adressering Mottagarens IP, e.g. 130.239.40.15 (32 bit) Mottagarens port, e.g. 8080 (16 bit) Returadress: Sändarens IP + port Multiplexing/demultiplexing Mottagarens IP + port TCP-Transmission Control Protocol Ett tillförlitligt protokoll Garanterar att paket är korrekta, ej duplicerade och i rätt ordning Undviker att överbelasta nätverket Adressering Mottagarens IP + port Returadress: Sändarens IP + port Multiplexing/demultiplexing Mottagarens och sändarens IP + port 4
IP - Internet Protocol Ett kommunikations-protokoll (på nätverksnivån) Tillhandahåller en datagram-service Adressering - IP-nummer i varje paket Best-effort -protokoll Försöker leverera varje paket Paket kan tappas bort, kastas om, dupliceras Sockets En abstraktion genom vilken applikationer kan skicka och ta emot data Ett API (Application Programming Interface) mellan applikationen och transportlagret Identifieras unikt IP-adress, port, transportprotokoll Applikation Socket UDP TCP IP Kopplingsnivån Fysiska nivån Portar Adresser per protokoll (port, host) UDP/13 TCP/13 TCP/1345 UDP/3242 5
Multiplexing/demultiplexing Port 1 Port 2 Port 3 UDP Demultiplexing baserad på portnummer UDP datagram IP Hur lokaliserar man en server? En server måste kunna återfinnas ip-nummer + port-nummer (e.g. 192.168.1.1 + 80) Fast plats för specifika servrar portnr 1-1023 oftast reserverade av OS:et vissa portnr är reserverade för vissa tjänster Katalogtjänst NIS - Network Information Service (Yellow pages) DNS - Domain Name System www.cs.umu.se 130.239.40.24 Standard -portar IANA (Internet Assigned Number Authority) tilldelar portnummer till kända applikationer http://www.iana.org/assignments/port-numbers Exempel: ftp-data 20/tcp File Transfer [Default Data] ftp 21/tcp File Transfer [Control] ssh 22/tcp SSH Remote Login Protocol telnet 23/tcp Telnet smtp 25/tcp Simple Mail Transfer http 80/tcp World Wide Web HTTP doom 666/udp Doom network game Id software Använd ej portarna 0 1023 för egna protokoll 6
Java-programmering UDP TCP Script (Trådar) http://java.sun.com/docs/books/tutorial/networking/ Connectionless (UDP) Datagram UDP Server Skapa socket serversocket = DatagramSocket() Klient Skapa socket clientsocket = DatagramSocket() Läs från serversocket Skapa adress och skicka datagram på clientsocket Skriv svar till Stäng serversocket serversocket Stäng clientsocket Läs svar på clientsocket Stäng clientsocket 7
UDP Server import java.io.*; import java.net.*; class UDPServer { public static void main(string args[]) throws Exception { DatagramSocket serversocket = new DatagramSocket(1337); byte[] recvbuf = new byte[8]; ByteArrayInputStream instream = new ByteArrayInputStream(recvBuf); DataInputStream in = new DataInputStream(inStream); DatagramPacket recvpack = new DatagramPacket(recvBuf, recvbuf.length); serversocket.receive(recvpack); double value = in.readdouble(); String name = recvpack.getaddress().gethostname(); System.out.println("Server got: " + value + from + name); UDP Klient import java.io.*; import java.net.*; class UDPClient { public static void main(string args[]) throws Exception { DatagramSocket clientsocket = new DatagramSocket(); ByteArrayOutputStream outstream = new ByteArrayOutputStream(8); DataOutputStream out = new DataOutputStream(outStream); out.writedouble(1.618); // Skriver 8 byte byte[] sendbuf = outstream.tobytearray(); InetAddress address = InetAddress.getByName("salt"); DatagramPacket sendpack = new DatagramPacket( sendbuf, sendbuf.length, address, 1337); clientsocket.send(sendpack); Connection Oriented (TCP) SERVER CLIENT Create socket Bind port number Listen Accept Read Write EOF Create socket Connect Write Read Close connection 8
TCP Server Klient Skapa socket welcomesocket = ServerSocket() Vänta på uppkoppling connectionsocket = welcomesocket.accept() TCP uppkoppling Skapa socket och koppla upp mot servern clientsocket = Socket() Läs från connectionsocket Skicka på clientsocket Skriv svar till connectionsocket Läs svar på clientsocket Stäng connectionsocket Stäng clientsocket TCP Server import java.io.*; import java.net.*; class TCPServer { public static void main(string args[]) throws Exception { ServerSocket welcomesocket = new ServerSocket(1337); // Only way to exit is Ctrl+C while (true) { Socket connectionsocket = server.accept(); InputStream is = connectionsocket.getinputstream(); OutputStream os = connectionsocket.getoutputstream(); BufferedReader in = new BufferedReader( new InputStreamReader(is)); PrintWriter out = new PrintWriter(os,true); String line = in.readline(); System.out.println( Server got: + line); out.println(line.touppercase()); TCP Klient import java.io.*; import java.net.*; class TCPClient { public static void main(string args[]) throws Exception { InetAddress address = InetAddress.getByName("salt"); Socket clientsocket = new Socket(address,1337); InputStream is = clientsocket.getinputstream(); OutputStream os = clientsocket.getoutputstream(); BufferedReader in = new BufferedReader(new InputStreamReader(is)); PrintWriter out = new PrintWriter(os,true); out.println( hello"); String line = in.readline(); System.out.println("Client got: " + line); 9
Nya kopplingsförsök Socket sock = null; InetAddress address = InetAddress.getByName( peppar ); boolean connected = false; while (!connected) { timeout tid try { sock = new Socket(); sock.connect(new InetSocketAddress(address,1337), 100); Thread.sleep(100); connected = true; catch (ConnectException e) { /* Försök i alla evighet */ InputStream is = socket.getinputstream(); OutputStream os = socket.getoutputstream(); Strömmar InputStream Läs ren byte-data (ettor och nollor) DataInputStream Från bytes till int, float, double, etc. Se upp med byte/bit-ordningen mellan olika system (endianness) InputStreamReader Koppling från byte-ström till tecken-ström Se upp med teckenkodningen mellan olika system (charset) Scanner Läs text och konvertera till data Teckenkodning BufferedReader Läs in text OutputStream Skriv ren byte-data DataOutputStream OutputStreamWriter PrintWriter Skriv text som med System.out Teckenkodning BufferedWriter Skriv text. Fler sätt att hantera strömmar: Se Java API (http://java.sun.com/javase/6/docs/api/) Kan förenkla era testkörningar Skapa <filnamn>.bash Sätt rättigheter att köra scriptet chmod u+x <filnamn>.bash Exempel: Script #!/bin/sh ssh scanner "cd edu/doi/lab1; java Ring tcp 12345 processor 12345" & ssh processor "cd edu/doi/lab1; java Ring tcp 12345 internet 12345" & ssh internet "cd edu/doi/lab1; java Ring tcp 12345 scanner 12345" & Om ni har program som kör i alla evighet Logga in på maskinen ssh <maskinnamn> Skriv ps för att lista alla processer som du kör Du kan ha en eller flera processer som heter java igång Enklast att skriva killall java så stängs alla dina java-program Eller skriv kill <pid> där pid är numret för den process som skenat iväg 10
Trådar i Java (föreläsning 5) public class TestThreads { public static void main(string[] args) throws java.io.ioexception { System.out.println("Starting 5 threads..."); for (int i = 0 ; i < 5 ; i++) new ExampelThread(i).start(); System.out.println("5 threads started"); public class ExampelThread extends Thread { private int i; public ExampelThread(int i) { super("exampelthread"); this.i = i; public void run() { System.out.println("Hallo from thread " + i); 11