Lez. 41 Alma Mater Studiorum - Universita' di Bologna Sede di Cesena Reti di Calcolatori L'interfaccia socket in Java Vedi: Sun, Java Networking – Tutorial. B. Eckel, Thinking in Java, 2nd Ed., pagg Copyright © by Claudio Salati.
2 Socket Java e socket C L’API socket in Java, a differenza di quella in C, non e’ coerentemente multiprotocollo, ma e’ largamente orientata a gestire comunicazioni solo nel dominio internet. Esiste in teoria una classe generica SocketAddress, ma c’e’ poi solo la classe derivata InetSocketAddress. Nei costruttori degli oggetti socket si fa normalmente riferimento direttamente a indirizzi del dominio internet. Nell’interfaccia di alcuni metodi delle classi socket compaiono direttamente indirizzi internet. L’API Android per comunicare su Bluetooth e’ basata su un insieme di classi/socket ad hoc. Mentre i socket C si presentano direttamente come una estensione del sistema operativo (un socket, come un file, e’ accessibile tramite file descriptor), i socket in Java sono legati allo specifico ambiente di programmazione: i socket sono classi/oggetti. N.B.: in effetti l’accesso ai file in C e’ possibile sia tramite l’API di sistema Unix (file descriptor) sia tramite l’API della libreria standard C (ADT FILE ).
3 Socket Java e socket C Mentre in C i socket sono tutti, a livello di linguaggio, di un unico tipo, in Java esistono diverse classi di socket, a seconda del protocollo che interfacciano (TCP vs. UDP) e a seconda del ruolo che assumono nella comunicazione (initiator vs. responder nel setup della connessione). Alla fine pero’ le operazioni di trasmissione/ricezione dati sono ricondotte (almeno per i socket TCP, ma anche per i socket Bluetooth-Android) alle normali modalita’ Java di lettura e scrittura su file. Cosi’ come nel mondo C ci si e’ ricondotti all’utilizzo delle due system call read() e write(), definite per operare su file descriptor relativi a qualunque tipo di risorsa reale. In realta’ nel costruttore socket() del C uno degli argomenti in ingresso e’ il tipo del servizio di comunicazione offerto dal socket, ma tutti i tipi di socket sono comunque rappresentati da un unico ADT.
4 Indirizzi Internet: classe InetAddress. 1 This class represents an Internet Protocol (IP) address. byte[] getAddress() Returns the raw IP address of this InetAddress object. The result is in network byte order. String getHostAddress() Returns the IP address of this InetAddress object string in textual presentation (decimal dotted notation, e.g. “ ”). String getHostName() Gets the host name for this IP address (of this InetAddress object). If this InetAddress was created with a host name, this host name will be remembered and returned. Otherwise, a reverse name lookup will be performed and the result will be returned based on the system configured name lookup service.
5 Indirizzi Internet: classe InetAddress. 2 static InetAddress getByAddress(String host, byte[] addr) Creates an InetAddress based on the provided host name and IP address. No name service is checked for the validity of the address. The host name can either be a machine name, such as " java.sun.com ", or a textual representation of its IP address (decimal dotted notation). static InetAddress getByName(String host) Creates an InetAddress based on the provided host name and determines the IP address of the host. The host name can either be a machine name, such as " java.sun.com ", or a textual representation of its IP address. If a literal IP address is supplied, only the validity of the address format is checked. static InetAddress getByAddress(byte[] addr) Returns an InetAddress object given the raw IP address. The argument is in network byte order. This method doesn't block, i.e. no reverse name service lookup is performed.
6 Indirizzi Internet: classe InetAddress. 3 Un InetAddress contiene due informazioni distinte: 1.Il nome della macchina, che puo’ pero’ essere assente. 2.L’indirizzo IP della macchina, che invece deve ovviamente essere presente perche’ l’ InetAddress sia effettivamente utile. Quando l’ InetAddress e’ creato a partire dal solo nome della macchina (costruttore getByName() ) e’ il costruttore stesso che si preoccupa di recuperare l’indirizzo IP (tramite name service lookup: cio’ significa che il metodo getByName() e’ bloccante). Se chiedo il nome della macchina che ha un certo InetAddress e questo era stato costruito a partire solo dall’indirizzo IP, il metodo getHostName(), effettuando un reverse name lookup, riesce a procurarselo. Notare che il costruttore che ha in ingresso sia il nome della macchina che il suo indirizzo IP non verifica la validita’ (la congruenza) delle due informazioni. Come potrebbe farlo? Dalla descrizione del costruttore, interrogando un name service (in terminologia DNS, invocando un resolver). E’ evidente che parte dell’ambiente di programmazione di rete e’ un name service che e’ capace di effettuare (avanti e indietro) la traduzione nome di una macchina (relativo) indirizzo IP E’ evidente che l’accesso al name service e’ costoso, perche’ il suo utilizzo e’ considerato bloccante per chi lo invoca.
7 Indirizzi Internet: classe InetSocketAddress. 1 This class implements an IP Socket Address IP address + port number It can also be a pair (hostname + port number), in which case an attempt will be made to resolve the hostname. If resolution fails then the address is said to be unresolved. It provides an immutable object used by sockets for binding, connecting, or as returned values. The wildcard is a special local IP address. It usually means "any" and can only be used for bind operations. Equivale alla costante INADDR_ANY dell'API socket C. N.B.: questa classe deriva dalla classe astratta SocketAddress, che “represents a Socket Address with no protocol attachment. As an abstract class, it is meant to be subclassed with a specific, protocol dependent, implementation”. Ma in realta’ l’unica sottoclasse esistente e’ InetSocketAddress, e nei metodi delle classi socket compaiono direttamente indirizzi internet.
8 Indirizzi Internet: classe InetSocketAddress. 2 InetSocketAddress(int port) Creates a socket address where the IP address is the wildcard address and the port number a specified value. A valid port value is between 0 and A port number of 0 will let the system pick up an ephemeral port in a bind operation. InetSocketAddress(InetAddress addr, int port) Creates a socket address from an IP address and a port number. A valid port value is between 0 and A port number of 0 will let the system pick up an ephemeral port in a bind operation. A null IP address will assign the wildcard address. InetSocketAddress(String hostname, int port) Creates a socket address from a hostname and a port number. An attempt will be made to resolve the hostname into an InetAddress. If that attempt fails, the address will be flagged as unresolved.
9 Indirizzi Internet: classe InetSocketAddress. 3 final int getPort() Gets the port number. final InetAddress getAddress() Gets the InetAddress. final String getHostName() Gets the hostname.
10 Tipi diversi di socket in un contesto CO Socket server di associazione (sa) Socket server di comunicazione (sc1) Socket server di comunicazione (sc2) Porta server Porta client 2Porta client 1 Socket client (sc-ac-1)Socket client (sc-ac-2) Connessione 1Connessione 2 Porta client 0 Socket client (sc-ac-0)
11 Socket Sono definite diverse classi per realizzare i diversi ruoli in cui un socket puo' essere utilizzato Infatti a ruoli diversi corrispondono diversi insiemi di operazioni applicabili Socket per la comunicazione connectionless: classe DatagramSocket Socket per la comunicazione connection-oriented classe Socket rappresenta un socket client (connesso o non connesso) un socket server di comunicazione (connesso) classe ServerSocket rappresenta un socket server di associazione (connessione)
12 Classe DatagramSocket This class represents a socket for sending and receiving datagram packets. Rappresenta il meccanismo di accesso ad una porta UDP A datagram socket is the sending or receiving point for a packet delivery service (servizio di comunicazione a messaggi). E' definita anche la classe DatagramPacket che rappresenta un datagram UDP. In Java la classe DatagramPacket non rappresenta solo il 4SDU, cioe’ il messaggio che il cliente del Servizio di Trasporto UDP vuole inviare o ha ricevuto dal proprio pari. Un DatagramPacket contiene anche informazioni aggiuntive.
13 Classe DatagramSocket Costruttori: DatagramSocket() Constructs a datagram socket and binds it to any available port on the local host machine (indirizzo IP wildcard). Quindi il socket e’ bind -ato all’ InetSocketAddress InetSocketAddress(0). DatagramSocket(int port) Constructs a datagram socket and binds it to the specified port on the local host machine (indirizzo IP wildcard). DatagramSocket(int port, InetAddress laddr) Creates a datagram socket, bound to the specified local address. DatagramSocket(SocketAddress bindaddr) Creates a datagram socket, bound to the specified local socket address. If the address bindaddr is null, creates an unbound socket.
14 Classe DatagramSocket Metodi: void bind(SocketAddress addr) Binds this DatagramSocket to a specific address & port. void connect(SocketAddress addr) Connects this socket to a remote socket address (IP address + port number). void disconnect() Disconnects the socket. SocketAddress getLocalSocketAddress() Returns the address of the endpoint this socket is bound to, or null if it is not bound yet. SocketAddress getRemoteSocketAddress() Returns the address of the endpoint this socket is connected to, or null if it is unconnected.
15 Classe DatagramSocket Metodi: void receive(DatagramPacket p) Receives a datagram packet from this socket. When this method returns, the DatagramPacket 's buffer is filled with the data received. The datagram packet also contains the sender's IP address, and the port number on the sender's machine. This method blocks until a datagram is received. The length field of the datagram packet object contains the length of the received message. If the message is longer than the packet's length, the message is truncated. void send(DatagramPacket p) Sends a datagram packet from this socket. The DatagramPacket includes information indicating the data to be sent, its length, the IP address of the remote host, and the port number on the remote host.
16 Classe DatagramSocket Metodi: void setTrafficClass(int tc) Sets traffic class (QoS, Quality of Service) or type-of-service (TOS) octet in the IP datagram header for datagrams sent from this DatagramSocket. void setBroadcast(boolean on) Enable/disable SO_BROADCAST. void close() Closes this datagram socket. Dove e’ l’informazione di destinazione/mittente nei due metodi send()/receive() ? Nel datagram packet!
17 Classe DatagramPacket Costruttori: DatagramPacket(byte[] buf, int length) Constructs a DatagramPacket for receiving packets of length (fino a) length. The length argument must be less than or equal to buf.length. DatagramPacket(byte[] buf, int length, SocketAddress address) Constructs a datagram packet for sending packets of length length to the specified port number on the specified host. DatagramPacket(byte[] buf, int length, InetAddress address, int port) Constructs a datagram packet for sending packets of length length to the specified port number on the specified host.
18 Classe DatagramPacket Metodi: SocketAddress getSocketAddress() Gets the SocketAddress (usually IP address + port number) of the remote host that this packet is being sent to or is coming from. void setSocketAddress(SocketAddress address) Sets the SocketAddress (usually IP address + port number) of the remote host to which this datagram is being sent. byte[] getData() Returns the data buffer. int getLength() Returns the length of the data to be sent or the length of the data received. void setData(byte[] buf) Set the data buffer for this packet. void setLength(int length) Set the length for this packet.
19 Classe Socket Questa classe rappresenta: un socket TCP client, connesso o non connesso. un socket TCP server di comunicazione connesso. Una istanza di Socket e' associata (in pratica): a una connessione TCP in caso di socket connesso. ad una porta TCP in caso di socket cliente non connesso. Una volta che un socket e' connesso gli si possono richiedere l' InputStream e l' OutputStream ad esso associati: InputStream getInputStream() OutputStream getOutputStream() si puo' leggere dal socket tramite le normali operazioni di lettura eseguibili sull' InputStream ad esso associato. si puo' scrivere sul socket tramite le normali operazioni di scrittura eseguibili sull' OutputStream ad esso associato.
20 Classe Socket Costruttori (1): Socket() Creates an unconnected stream socket. Ma a quale local address e’ bind -ato il socket? Socket(InetAddress address, int port) Creates a stream socket and connects it to the specified port number at the specified IP address. Ma a quale local address e’ bind -ato il socket? Socket(InetAddress address, int port, InetAddress localAddr, int localPort) Creates a stream socket and connects it to the specified remote address on the specified remote port. The socket will also bind() to the local address and port supplied.
21 Classe Socket Costruttori (2): Socket(String host, int port) Creates a stream socket and connects it to the specified port number on the named host. Ma a quale local address e’ bind -ato il socket? Socket(String host, int port, InetAddress localAddr, int localPort) Creates a stream socket and connects it to the specified remote host on the specified remote port. The socket will also bind() to the local address and port supplied.
22 Classe Socket Metodi: void bind(SocketAddress bindpoint) Binds the socket to a local address. void connect(SocketAddress endpoint) Connects this socket to the server. SocketAddress getLocalSocketAddress() Returns the address of the endpoint this socket is bound to, or null if it is not bound yet. SocketAddress getRemoteSocketAddress() Returns the address of the endpoint this socket is connected to, or null if it is unconnected. void close() Closes this socket.
23 Classe Socket Metodi: InputStream getInputStream() Returns an input stream for this socket. OutputStream getOutputStream() Returns an output stream for this socket. Esempio:... int serverPort = (new Integer(args[1])).intValue(); Socket socket = new Socket(args[0], serverPort); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream();...
24 Classe Socket Metodi: void sendUrgentData(int data) Send one byte of urgent data on the socket. The urgent byte is sent after any preceding writes to the socket OutputStream and before any future writes to the OutputStream. void setOOBInline(boolean on) Enable/disable OOBINLINE (receipt of TCP urgent data). By default, this option is disabled and TCP urgent data received on a socket is silently discarded. If the user wishes to receive urgent data, then this option must be enabled. When enabled, urgent data is received inline with normal data. Note, only limited support is provided for handling incoming urgent data. In particular, no notification of incoming urgent data is provided and there is no capability to distinguish between normal data and urgent data unless provided by a higher level protocol.
25 Classe Socket Metodi: void setKeepAlive(boolean on) Enable/disable SO_KEEPALIVE. void setReuseAddress(boolean on) Enable/disable the SO_REUSEADDR socket option. void setTcpNoDelay(boolean on) Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm). void setTrafficClass(int tc) Sets traffic class (QoS, Quality of Service) or type-of-service (TOS) octet in the IP header for packets sent from this socket. boolean isConnected() Returns the connection state of the socket.
26 Classe InputStream.1.1 This abstract class is the superclass of all classes representing an input stream of bytes. “Byte”? Cioe’? Un “byte” e’ dato di 8 bit in ordine dato: ma solo un dato! Quale e’ l’informazione associata? In analogia con il linguaggio C, un “byte” corrisponde ad un oggetto signed char o ad un oggetto unsigned char ? Che relazione c’e’ tra un “byte” di un InputStream e un byte Java? Applications that need to define a subclass of InputStream must always provide a method that returns the next byte of input. E’ evidentemente l’astrattezza di questo metodo nella classe InputStream che la rende astratta!
27 Classe InputStream.1.2 public void close() throws IOException Closes this input stream and releases any system resources associated with the stream. public int available() throws IOException Returns an estimate of the number of bytes that can be read from this input stream without blocking by the next invocation of a method for this input stream. A single read of this many bytes will not block, but may read fewer bytes. The available() method for class InputStream always returns 0. This method should be overridden by subclasses. A subclass' implementation of this method may choose to throw an IOException if this input stream has been closed by invoking the close() method.
28 Classe InputStream.2 Cio’ che rende astratta la classe InputStream e’ che e’ astratto il suo metodo read(). E’ quindi questo metodo read() che deve essere definito da ogni classe concreta derivata da InputStream. Questo e’ vero in particolare per la classe dell’oggetto ritornato dal metodo getInputStream() della classe Socket. public abstract int read() throws IOException Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255. N.B.: quindi l’ InputStream e’ visto come una sequenza di byte senza segno! If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.
29 Classe InputStream.3.1 public int read(byte[] b) throws IOException Reads some number of bytes from the input stream and stores them into the buffer array (di byte, cioe’ di byte con segno) b. N.B.: quindi l’ InputStream e’ visto come una sequenza di byte con segno! The number of bytes actually read is returned as an integer. This method blocks until input data is available, end of file is detected, or an exception is thrown. If b is null, a NullPointerException is thrown. If the length of b is zero, then no bytes are read and 0 is returned; otherwise, there is an attempt to read at least one byte.
30 Classe InputStream.3.2 public int read(byte[] b) throws IOException Continua: If no byte is available because the stream is at end of file, the value -1 is returned; otherwise, at least one byte is read and stored into b. The first byte read is stored into element b[0], the next one into b[1], and so on. The number of bytes read is, at most, equal to the length of b. The read(b) method for class InputStream has the same effect as read(b, 0, b.length). public int read(byte[] b) throws IOException { return (read(b, 0, b.length)); }
31 Classe InputStream.4.1 public int read(byte[] b, int off, int len) throws IOException Reads up to len bytes of data from the input stream into an array of bytes (in realta’, di byte, con segno). An attempt is made to read as many as len bytes, but a smaller number may be read, possibly zero. The number of bytes actually read is returned as an integer. This method blocks until input data is available, end of file is detected, or an exception is thrown. If b is null, a NullPointerException is thrown. If off is negative, or len is negative, or off+len is greater than the length of the array b, then an IndexOutOfBoundsException is thrown.
32 Classe InputStream.4.2 public int read(byte[] b, int off, int len) throws IOException Continua: If len is zero, then no bytes are read and 0 is returned; otherwise, there is an attempt to read at least one byte. If no byte is available because the stream is at end of file, the value -1 is returned; otherwise, at least one byte is read and stored into b. The first byte read is stored into element b[off], the next one into b[off+1], and so on. The number of bytes read is, at most, equal to len. In every case, elements b[0] through b[off] and elements b[off+len] through b[b.length-1] are unaffected.
33 Classe InputStream.4.3 public int read(byte[] b, int off, int len) throws IOException Continua: The read(b, off, len) method for class InputStream simply calls the method read() repeatedly. If the first such call results in an IOException, that exception is returned from the call to the read(b, off, len) method. If any subsequent call to read() results in a IOException, the exception is caught and treated as if it were end of file: the bytes read up to that point are stored into b and the number of bytes read before the exception occurred is returned. Subclasses are encouraged to (override this method and) provide a more efficient implementation of this method.
34 Classe InputStream.5 public int read(byte[] b, int off, int len) throws IOException { if (len==0) return(0); int bRead; int i; bRead = read(); if (bRead<0) return(bRead); // EOF b[off] = (byte)(bRead < 128 ? bRead : ( bRead)); for (i=1, off+=1; i<len; i+=1, off+=1) { try { // N.B. cosa succede se available() non e’ stata ridefinita? if (available()<=0) return(i); bRead = read(); b[off] = (byte)(bRead < 128 ? bRead : ( bRead)); } catch (IOException e) { return(i); } return(i); }
35 byte Java Intero con segno nel range Rappresentazione concreta su 1 byte, complemento-a-2 static byte unsignedByteInInt2byte(int b) { // 0 <= b <= 255 return ((byte)(b < 128 ? b : (-256+b))); } Byte (senza segno) e byte Java
36 Ma in realta’ … Q.Consider the following code snippet: int x = 241; byte y = (byte) x; System.out.println("y is " + y); I am getting the output as -15. How did the result come as -15? Please explain. A.Byte can take only 8 bits with the 8th bit for sign(+ or -). 241 = 's complement of is 1111 which is 15. Q:Quindi cosa succede quando converto a byte un valore int ? Byte (senza segno), int e byte Java
37 Socket, InputStream e OutputStream Il metodo getInputStream() di un socket non ritorna ovviamente un oggetto di classe InputStream in senso stretto, ma un oggetto di una classe concreta derivata da InputStream La classe concreta dell’oggetto ritornato dal socket Definisce ovviamente (necessariamente) il metodo read() (altrimenti la classe non sarebbe concreta) Ridefinisce, per ragioni di efficienza, il metodo read(byte[] b, int off, int len) Ridefinisce, ragionevolmente, il metodo available() Discorso analogo vale ovviamente, in modo simmetrico, per la classe OutputStream e per l’oggetto ritornato dal metodo getOutputStream() della classe Socket
38 Classe OutputStream.1 This abstract class is the superclass of all classes representing an output stream of bytes (“byte”? Cioe’? Vedi classe InputStream ). An output stream accepts output bytes and sends them to some sink. Applications that need to define a subclass of OutputStream must always provide at least a method that writes one byte of output. public void close() throws IOException Closes this output stream and releases any system resources associated with this stream. The general contract of close is that it closes the output stream. A closed stream cannot perform output operations and cannot be reopened. public void flush() throws IOException Flushes this output stream and forces any buffered output bytes to be written out. The general contract of flush is that calling it is an indication that, if any bytes previously written have been buffered by the implementation of the output stream, such bytes should immediately be written to their intended destination.
39 Classe OutputStream.2.1 public abstract void write(int b) throws IOException Writes the specified byte (cioe’? Vedi seguito!) to this output stream. The general contract for write is that one byte is written to the output stream. The byte to be written is the eight low-order bits of the argument b. The 24 high-order bits of b are ignored. N.B. il write() di valori int come -1 e 255 (o 65535) produce esattamente lo stesso effetto. Il byte piu’ leggero del valore int e’ scritto nell’ OutputStream, indipendentemente dal significato complessivo del valore int.
40 Classe OutputStream.2.2 public void write(byte[] b) throws IOException Writes b.length bytes from the specified byte array to this output stream. The general contract for write(b) is that it should have exactly the same effect as the call write(b, 0, b.length). N.B.: nota che, a differenza di quanto avviene con la system call write() del C, questo, come tutti i metodi write() della classe Java OutputStream, termina solo quando tutti i byte indicati sono stati scritti sullo stream. public void write(byte[] b) throws IOException { return (write(b, 0, b.length)); }
41 Classe OutputStream.3 public void write(byte[] b, int off, int len) throws IOException Writes len bytes from the specified byte array starting at offset off to this output stream. The general contract for write(b, off, len) is that some of the bytes in the array b are written to the output stream in order; element b[off] is the first byte written and b[off+len-1] is the last byte written by this operation. If off is negative, or len is negative, or off+len is greater than the length of the array b, then an IndexOutOfBoundsException is thrown. The write() method of OutputStream calls the write() method of one argument on each of the bytes to be written out. Subclasses are encouraged to override this method and provide a more efficient implementation.
42 Lettura di (esattamente) nch byte su socket CO byte [] readNch (InputStream in, int nch) { byte [] b = new byte[nch]; int n = 0, j = 0; try { while (true) { n = in.read(b, j, 1); if (n errore if (n==0) continue; // impossibile j += 1; if (j== nch) return b; } } catch (Exception e) { System.err.println("readNch exception:" + e); System.exit(1); } return null; } //readNch, Copyright © by D. Romagnoli
43 Scrittura di (esattamente) nch byte su socket CO void writeNch(OutputStream out, byte [] b, int nch) { try { out.write(b, 0, nch); } catch (Exception e) { System.err.println ("writeNch exception:" + e); System.exit(1); } } //writeNch, Copyright © by D. Romagnoli
44 Classe ServerSocket Questa classe rappresenta un socket server, su cui il processo server attende nuove richieste di connessione: Socket accept() Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made. A new Socket is created and returned. Una istanza di ServerSocket e' associata ad una porta TCP. (in realta’ a una porta connessa all porta remota :0) A seguito della creazione della connessione TCP il ServerSocket crea un Socket e lo associa alla connessione stessa. Il ServerSocket di per se' stesso non e' associato alla connessione che e’ stata creata e rimane disponibile per attendere nuove richieste di connessione.
45 Classe ServerSocket Costruttori: ServerSocket() Creates an unbound server socket ServerSocket(int port) Creates a server socket, bound to the specified port. ServerSocket(int port, int backlog) Creates a server socket and binds it to the specified local port number, with the specified backlog. ServerSocket(int port, int backlog, InetAddress bindAddr) Creates a server socket with the specified port, listen backlog, and local IP address to bind to. N.B.: un ServerSocket puo’ essere costruito gia’ in stato listen ing: Non esiste un metodo esplicito listen(). Ovviamente, perche’ un socket possa essere in stato listen ing esso deve essere gia’ bind ato!
46 Classe ServerSocket Metodi: void bind(SocketAddress endpoint) Binds the ServerSocket to a specific address (IP address and port number). void bind(SocketAddress endpoint, int backlog) Binds the ServerSocket to a specific address (IP address and port number). Socket accept() Listens for a connection to be made to this socket and accepts it. SocketAddress getLocalSocketAddress() Returns the address of the endpoint this socket is bound to, or null if it is not bound yet. void setReuseAddress(boolean on) Enable/disable the SO_REUSEADDR socket option. void close() Closes this socket.
47 System call select() Come mai in Java non esiste per operare sui socket un metodo equivalente alla system call select() del C? In realta’ una funzionalita’ tipo select() alla fine e’ stata aggiunta, ma e’ goffa e poco utilizzata. In C lo stile di programmazione classico e’ Sincrono Single-thread (con l’eccezione della gestione dei segnali, che comunque non e’ di uso generalizzato) In Java lo stile di programmazione classico e’ Sincrono Multi-thread In Java il problema dell’accesso contemporaneo di un processo a piu’ risorse e’ risolto associando una thread diversa ad ogni flusso dati, cosi’ che ogni thread non debba accedere ad un certo istante a piu’ di una risorsa.