Sockets - auf Matthias

Werbung
Netzprogrammierung:
Kommunikation über Sockets
Robert Tolksdorf und Peter Löhr
Überblick
• Internet-Dienste und -Protokolle
• IP-Adressen und Rechnernamen
• Portnummern
• Kommunikation über Sockets
• TCP
• UDP
• Multicast
Robert Tolksdorf und Peter Löhr
2
Internet-Dienste und -Protokolle
Robert Tolksdorf und Peter Löhr
Was ist das Internet ?
• (hardware-bezogene Sicht:) Ein weltweiter Verbund von
Rechnern, die über Netze Daten austauschen können
• Zusammenschalten von lokalen Netzen zum Internet
• dabei notwendige Verarbeitung von Datenpaketen
• (netzbezogene Sicht:) Eine Familie von Kommunikationsdiensten und -protokollen
• Spezifikation von Kommunikationsdiensten
• Spezifikation von Protokollen zur Dienst-Implementierung
• (anwendungsbezogene Sicht:) Ein offenes System, in
dem Anwendungsdienste angeboten und genutzt werden
können
Robert Tolksdorf und Peter Löhr
4
Vermittlungsdienst im Internet
• Das Internet Protocol IP ermöglicht “internetworking”
durch Etablierung von Datenformaten und
Interaktionsregeln, die von unterschiedlichen
Netztechnologien abstrahieren
• IP erbringt Vermittlungsdienst: Übertragung von
Datenpaketen von Quellrechner zu Zielrechner, ggfls.
über Zwischenstationen
x.inf.fu-berlin.de
a.cs.tu-berlin.de
y.inf.fu-berlin.de
b.cs.tu-berlin.de
z.inf.fu-berlin.de
c.cs.tu-berlin.de
Ethernet
Robert Tolksdorf und Peter Löhr
ATM
5
IP-Adressen
• Identifizierung eines Rechners im Netz durch IP-Adresse,
auch Internet-Adresse
• aktuell 32 Bit, notiert als 4 Bytes in Dezimaldarstellung,
z.B. 130.149.27.12
• IP-Adresse ist per Software festgelegt (wird im
Lokalnetz auf eine physikalische Netzadresse abgebildet,
die MAC-Adresse [media access control] )
• Routing-Funktionalität des IP-Protokolls besorgt das
Weiterleiten von Paketen über Zwischenstationen zur
endgültigen Zielstation (mit Hilfe von routing tables)
Robert Tolksdorf und Peter Löhr
6
Rechnernamen und DNS
• mnemonische Identifizierung von Rechnern durch
Namen, z.B. bobspc, nawab, troll (im lokalen Netz)
• Weltweit hierarchischer Namensraum:
Domain Name System (DNS) mit Namen wie
• troll.mi.fu-berlin.de für den Rechner 160.45.45.50
• Domain Name Service (DNS) ist zuständig für die
Zuordnung zwischen Namen und Adressen
(Empfehlung: http://ping.eu)
Robert Tolksdorf und Peter Löhr
7
Systemfunktionen
#include <netdb.h>
struct hostent *gethostbyname(char *hostname)
liefert den Verweis auf einen Verbund, der u.a. die
IP-Adresse(n) des genannten Rechners enthält
struct hostent *gethostbyaddr
(char *addr, int len, int type)
arbeitet umgekehrt
(Implementierung: DNS befragen - oder /etc/hosts oder ...)
#include <netinet/in.h>
unsigned long inet_addr(char *ptr)
wandelt eine IP-Adresse in die 32-Bit-Darstellung
char *inet_ntoa(struct in_addr addr)
arbeitet umgekehrt
Robert Tolksdorf und Peter Löhr
8
... und mit java.net.InetAddress
• Klasse InetAddress für Adress-Objekte:
• byte[] getAddress()
liefert IP-Adresse als 4-Byte-Feld, z.B. {10,1,2,12}
(network byte order: big-endian!)
• String getHostAddress()
… als Zeichenkette in Punktnotation, z.B. “10.1.2.12“
• String getHostName()
liefert den Namen
Robert Tolksdorf und Peter Löhr
9
... und mit java.net.InetAddress
• Erzeugung von Adress-Objekten:
• static InetAddress getByName(String host)
Beispiele:
w3c =
InetAddress.getByName(“www.w3c.org”);
mypc = InetAddress.getByName(“localhost”); (“loopback interface”)
nix =
InetAddress.getByName(“10.1.2.12”);(!)
• static InetAddress getByAddress(byte[] addr)
Beispiel:
myserver =
InetAddress.getByAddress(new byte[] {10,1,2,12});
• static InetAddress getLocalHost()
liefert Adress-Objekt, mit dem der lokale Rechner von außen erreicht
werden kann. Gewöhnlich gilt also nicht
InetAddress.getLocalHost().equals(
InetAddress.getByName(“localhost“))
sondern:
Robert Tolksdorf und Peter Löhr
10
System.out.println(InetAddress.getByName("localhost"));
produziert
localhost/127.0.0.1
System.out.println(InetAddress.getLocalHost());
produziert imp048229.vpn.mi.fu-berlin.de/10.1.246.230
(oder ähnlich)
Robert Tolksdorf und Peter Löhr
11
Beispiel
• Namen umwandeln in Punktnotation:
import java.net.*;
class IP {
public static void main(String[] args) throws Exception {
InetAddress addr =
InetAddress.getByName(args[0]);
System.out.println(addr.getHostAddress());
}
}
$ java IP troll.mi.fu-berlin.de
160.45.45.50
$
Robert Tolksdorf und Peter Löhr
12
Transportdienste
• Transportdienst besorgt den Transport von Daten zwischen
Kommunikationsendpunkten (= virtuelle Netzanschlüsse),
die von Prozessen verwendet werden.
• Die Implementierung orientiert sich an der Spezifikation
zugehöriger Transportprotokolle und benutzt den IP-Dienst
• Zwei typische Transportdienste im Internet:
• UDP (user datagram protocol) unterscheidet sich nur
unwesentlich vom IP-Dienst: eine Nachricht wird als
Datagramm auf den Weg durchs Netz geschickt, ohne dass
das Eintreffen am Zielendpunkt garantiert wird
(verbindungsloser Dienst).
• TCP (transmission control protocol) etabliert einen
zuverlässigen Byte-Strom zwischen Quelle und Ziel, die zu
diesem Zweck eine virtuelle Verbindung herstellen
(verbindungsorientierter Dienst)
Robert Tolksdorf und Peter Löhr
13
Ports und Sockets
• Ein Port ist eine Nummer im Bereich [0..65535] zur
Identifizierung von Anbietern von Anwendungsdiensten
und deren Klienten (synonym auch Portnummer).
Der Bereich [0..1023] ist für Standarddienste reserviert.
• Ein Socket (dt. Steckdose) ist ein mit einer Portnummer
versehener Kommunikationsendpunkt auf Anbieterseite
oder Klientenseite. Im Fall einer TCP-Verbindung besteht
eine Assoziation eines anbieterseitigen Sockets mit einem
klientenseitigen Socket.
Robert Tolksdorf und Peter Löhr
14
TCP
Transmission Control Protocol
Robert Tolksdorf und Peter Löhr
TCP Sockets
• Erzeugung eines Socket:
#include <sys/socket.h>
int socket(int family, int type, int protocol)
prozesslokale
SocketNummer
ProtokollFamilie:
AF_INET
Dienst:
TCP
Protokoll:
0
• Netzweit gültige Benennung eines Socket durch einen
Anbieter - mit Reservierung eines freien Ports:
int bind(int socket,
struct sockaddr *address, wählt Portnummer
int addrlen)
und IP-Adresse
Robert Tolksdorf und Peter Löhr
16
TCP Sockets
• Festlegung der akzeptierten Warteschlangenlänge:
int listen(int socket, int backlog)
• Annahme des Verbindungswunschs eines Klienten:
int accept(int socket,
struct sockaddr *client,
int *addrlen)
Nummer eines neugeschaffenen (!) Socket, der mit dem
Socket des Klienten verbunden ist. Damit ist zwischen
beiden Sockets ein bidirektionaler Kommunikationskanal
eingerichtet. Beachte: der neue Socket trägt die gleiche
Portnummer wie der alte; wegen seiner Assoziation mit
dem Port des Klienten stellt er dennoch einen neuen
Kommunikationsendpunkt dar.
Robert Tolksdorf und Peter Löhr
17
TCP Sockets
• Was tut der Klient?
• Socket erzeugen: wie auf S. 16
• (wahlweise:) Socket benennen: wie auf S. 16;
falls die Benennung unterbleibt, wählt das System im nächsten
Schritt irgendeine freie Portnummer.
• Verbindungswunsch an den Server richten:
#include <sys/socket.h>
int connect(int socket,
struct sockaddr *server,
int addrlen)
• Nach Rückkehr von connect Benutzung der Verbindung auf
•
beiden Seiten mit read/write auf den jeweiligen Sockets
Abbau der Verbindung mit int close(int socket) (einseitig oder
beidseitig)
Robert Tolksdorf und Peter Löhr
18
TCP Sockets
1. Anbieter reserviert Port
bind
2. Anbieter macht sich bereit
3. Anbieter wartet auf Verbindungswunsch, Klient schickt
Verbindungswunsch
4. Klient und Anbieter
sind verbunden
- bidirektional!
5. Verbindung wird
abgebaut
Robert Tolksdorf und Peter Löhr
listen
connect
accept
read/write
read/write
close
close
19
TCP Sockets
Klienten
47111
Server
12345
12346
22
22
22
22
22
43210
( Port 22: Dienst ssh )
Robert Tolksdorf und Peter Löhr
20
TCP Sockets
• ... und nicht vergessen:
eventuell unterschiedliche Datenrepräsentation in beiden
Rechnern! Das kann selbst dann fatal sein, wenn nur Zeichen
übertragen werden (Byte-Ordnung)!
• Typische Hilfsfunktionen dafür: byte ordering routines
#include <netinet/in.h>
u_long htonl(u_long hostlong)
u_short htons(u_short hostshort)
u_long ntohl(u_long netlong)
u_short ntohs(u_short netshort)
Robert Tolksdorf und Peter Löhr
21
TCP Sockets
• Klient "netcat" stellt Verbindung mit einem Dienstanbieter her
und erlaubt Interaktion über Tastatur/Bildschirm:
$ nc localhost 79
(Port 79: Dienst finger)
lohr
Login: lohr
Name: Peter Löhr
Directory: /Users/lohr
Shell: /bin/bash
On since Wed Oct 1 09:14 (CEST) on console, idle 17 days 8:46 (messa
On since Fri Oct 17 15:20 (CEST) on ttyp1
No Mail.
No Plan.
$
$ nc nawab.mi.fu-berlin.de 13
(Port 13: Dienst daytime)
Sat Oct 18 18:13:11 2008
$
Robert Tolksdorf und Peter Löhr
22
Socket-Objekte in Java
• Paket java.net stellt geeignete public Klassen bereit:
• abstract class SocketAddress { ...
// Socket-Namen
}
• class InetSocketAddress extends SocketAddress {
// Socket-Namen für Internet-Dienste,
// bestehend aus IP-Adresse und Portnummer
public InetSocketAddress(String hostname, int port) ...
}
Robert Tolksdorf und Peter Löhr
23
Socket-Objekte in Java
• class Socket {
// Klienten-Sockets
public Socket() ...// unbenannte, unverbundene Sockets
public Socket(String host, int port) throws ...
// verbundene Sockets - mit port auf host
public void bind(SocketAddress bindpoint) throws ...
// benennt den Socket mit bindpoint
public void connect(SocketAddress endpoint) throws ...
// verbindet den Socket mit einem Anbieter// Socket mit dem Namen endpoint
public void close() throws ...
// macht den Socket unbenutzbar und trennt
// eine eventuell existierende Verbindung
public OutputStream getOutputStream() throws ...
public InputStream getInputStream() throws ...
// Senden und Empfangen von Bytes
}
Robert Tolksdorf und Peter Löhr
24
Socket-Objekte in Java
• class ServerSocket {
// Anbieter-Sockets
public ServerSocket() throws ...
// unbenannte, unverbundene Sockets
public ServerSocket(int port, int backlog) throws ...
// benannte, empfangsbereite Sockets
public void bind(SocketAddress endpoint, int backlog) throws ...
// benennt den Socket
public Socket accept() throws ...
// liefert einen neuen Socket, der mit dem
// Socket eines Klienten verbunden ist
public void close() throws ...
// macht den Socket unbenutzbar und trennt
// eine eventuell existierende Verbindung
}
Robert Tolksdorf und Peter Löhr
25
Beispiel Echo-Dienst
• Ein Echo-Dienst: Anbieter wartet auf Zeichenketten und
antwortet mit ähnlichen Zeichenketten
• Starten des Dienstes:
• Testen des Dienstes:
mypc: nc nawab 12345
ping
pong
risibisi
rosoboso
^C punt!
mypc:
Robert Tolksdorf und Peter Löhr
nawab: java Echo 12345 &
[1] 2011
nawab:
mit eigenem Klienten:
mypc: java Client nawab 12345
ping
pong
risibisi
rosoboso
^D
mypc:
26
Beispiel Echo-Dienst
import java.io.*;
import java.net.*;
public class Echo {
public static void main (String args[]) throws IOException {
ServerSocket listen = new ServerSocket(Integer.parseInt(args[0]));
while(true) {
// non-terminating server
Socket socket = listen.accept();
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
while (true) {
// end of input stream will close dialogue
String message = in.readLine();
if(message==null) break;
String answer = message.replace('i','o');
out.println(answer);
}
in.close(); out.close(); socket.close();
// ready to accept new client
}
}
}
Robert Tolksdorf und Peter Löhr
27
Beispiel Echo-Dienst
import java.io.*;
import java.net.*;
public class Client {
public static void main (String args[]) throws IOException {
Socket socket = new Socket(args[0], Integer.parseInt(args[1]));
PrintStream out = new PrintStream(socket.getOutputStream());
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
BufferedReader keyboard = new BufferedReader(
new InputStreamReader(System.in));
while(true) {
// ^D will close dialogue
String message = keyboard.readLine();
if(message==null) break;
out.println(message);
String answer = in.readLine();
System.out.println(answer);
}
in.close(); out.close(); socket.close();
}
}
Robert Tolksdorf und Peter Löhr
28
Beachte:
• Das Programm Client wickelt lediglich einen Dialog ab
und weiß nichts von dem kontaktierten Dienst - insofern
ähnelt es dem nc. Man probiere z.B.
• java Client localhost 13
• nc localhost daytime
• Der Dienst Echo ist insofern recht beschränkt, als er
nicht mehrere Dialoge gleichzeitig führen kann. Wer
den Dienst benutzen will, muss eventuell warten, bis ein
gerade aktiver Benutzer seinen Dialog beendet.
Robert Tolksdorf und Peter Löhr
29
UDP
User Datagram Protocol
Robert Tolksdorf und Peter Löhr
TCP vs. UDP
• TCP: Pakete werden geordnet und zuverlässig über eine
Verbindung transportiert. Effekt: zuverlässiger,
reihenfolgetreuer Byte-Strom.
• UDP: Ein Paket („Datagramm“) wird auf den Weg von
einem Socket zu einem anderen geschickt. Dass das
Datagramm am Ziel eintrifft ist nicht garantiert,
Reihenfolgetreue (FIFO) auch nicht.
Robert Tolksdorf und Peter Löhr
31
UDP Sockets
1. Anbieter reserviert Port
bind
2. Klient reserviert Port
bind
3. Klient/Anbieter senden und
empfangen Datagramme
bidirektional!
send
receive
4. Ports und Sockets
werden freigegeben
close
close
Robert Tolksdorf und Peter Löhr
32
Beispiel Echo-Dienst
• Variante des Echo-Dienstes von S. 25 - Starten:
$ java EchoUDP 12345 &
[1] 2011
$
• Testen des Dienstes:
$ nc -u localhost 12345
ping
pong
singing
songong
^C punt!
$
Robert Tolksdorf und Peter Löhr
(Option -u steht für UDP)
33
Beispiel Echo-Dienst
import java.net.*;
import java.io.*;
public class EchoUDP {
public static void main(String args[]) throws IOException {
byte[] inData = new byte[1024];
byte[] outData = new byte[1024];
DatagramPacket in = new DatagramPacket(inData, inData.length);
DatagramSocket socket = new DatagramSocket(
Integer.parseInt(args[0]));
while(true) {
// non-terminating server
socket.receive(in);
// wait for message
InetAddress senderAdress = in.getAddress();
int senderPort = in.getPort();
String message=new String(in.getData(), 0, in.getLength());
// build answer:
Robert Tolksdorf und Peter Löhr
34
Beispiel Echo-Dienst
outData = message.replace('i','o').getBytes();
DatagramPacket out = new DatagramPacket(
outData, outData.length,
senderAddress, senderPort);
socket.send(out);
// send answer
}
}
}
Beachte: Im Gegensatz zu TCP ist der empfangende Socket
nicht mit dem sendenden Socket verbunden. Daher müssen
die Absenderdaten senderAddress, senderPort für das richtige
Adressieren der Antwort explizit gehandhabt werden.
Robert Tolksdorf und Peter Löhr
35
... und ein passender Klient
import java.io.*;
import java.net.*;
public class ClientUDP {
public static void main (String args[]) throws IOException {
byte[] inData = new byte[1024];
byte[] outData = new byte[1024];
DatagramPacket in = new DatagramPacket(inData,inData.length);
InetAddress server = InetAddress.getByName(args[0]);
int port = Integer.parseInt(args[1]);
DatagramSocket socket = new DatagramSocket();
// chooses some available local port
BufferedReader keyboard = new BufferedReader(
new InputStreamReader(System.in));
// dialogue starts here:
Robert Tolksdorf und Peter Löhr
36
... und ein passender Klient
}
}
while(true) {
// ^D will close dialogue
String message = keyboard.readLine();
if(message==null) break;
outData = message.getBytes();
DatagramPacket out = new DatagramPacket(
outData, outData.length, server, port);
socket.send(out);
socket.receive(in);
String answer = new String(in.getData(),0,in.getLength());
System.out.println(answer);
}
socket.close();
$ java ClientUDP localhost 12345
Robert Tolksdorf und Peter Löhr
ping
pong
singing
songong
^D
$
37
Herunterladen