Esercitazione: Socket Java con connessione Sviluppare un applicazione C/S che effettui il trasferimento di un file dal client al server (put) usando una connessione. In particolare nel servizio: il client chiede all utente il nome di un file da trasferire, si connette al server (con java.net.socket), crea uno stream di output sulla connessione attraverso cui inviare il file selezionato, preceduto dal suo nome. Se anziché il nome del file l utente inserisce un asterisco, il client invia al server tutti i file di testo contenuti nel direttorio corrente. Ogni file è preceduto dal nome del file stesso. Server Sequenziale Std Input nome file client put file rete put file server file Std Output Server Concorrente il server attende una richiesta di connessione da parte del client (su java.net.serversocket), usa la socket (java.net.socket) prodotta dalla connessione per creare uno stream di input da cui riceve il nome del file e il file che stamperà poi a video, dopodiché chiude la connessione. In caso di invio ripetuto, la stessa connessione viene usata per tutti i file (nome e contenuto) fino al termine della connessione da parte del cliente nome file2 client client client nome file1 put file2 nome file3 put file1 put file3 rete file1 serverthread1 put file1 serverthread3 serverthread2 put file2 server put file3 file2 file3 Applicazioni Distribuite e Servizi di Rete Java socket stream - 1 Applicazioni Distribuite e Servizi di Rete Java socket stream - 2
Filtraggi Filtro Input FILTRO Output Un filtro è un programma che consuma tutto il suo input e porta l uscita sull output Possiamo pensare di combinarne in una pipeline Esempi di creazione stream di input da socket: DataInputStream insock = new DataInputStream(socket.getInputStream()); Un filtro potrebbe leggere da uno stream fino alla fine del file e poi lanciare in output delle indicazioni Vedi la trasferisci_a_byte InputStreamReader isr = new InputStreamReader(socket.getInputStream()); BufferedReader in = new BufferedReader(isr); Esempi di creazione stream di output su socket: DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream()); BufferedWriter bw = new BufferedWriter(osw); PrintWriter out = new PrintWriter( bw, true); Applicazioni Distribuite e Servizi di Rete Java socket stream - 3 Applicazioni Distribuite e Servizi di Rete Java socket stream - 4
Schema di soluzione: il Client 1. Creazione socket ed eventuale settaggio opzioni: socket = new Socket( addr, PutFileServerSeq.PORT); socket.setxxx( ); 2. Interazione da console con l utente: BufferedReader stdin = new BufferedReader( new InputStreamReader(System.in)); System.out.print("Domanda "); String richiesta = stdin.readline(); 3. Creazione dello stream di output sulla socket: outsock = new DataOutputStream(socket.getOutputStream()); 4. Creazione dello stream di input da file: infile = new DataInputStream( new FileInputStream(nomeFile)); 5. Invio dei dati al server: outsock.writeutf(nomefile); FileUtility.trasferisci_a_byte (infile, outsock); 6. Chiusura della socket: Schema di soluzione: il Server 1. Creazione socket ed eventuale settaggio opzioni: serversocket = new ServerSocket(PORT); serversocket.setreuseaddress(true); 2. Attesa/accettazione di richiesta di connessione: clientsocket = serversocket.accept(); 3. Creazione dello stream di input sulla socket: insock = new DataInputStream( clientsocket.getinputstream()); 4. Ricezione dei dati dal client e invio dei dati sulla console in uscita nomefile=insock.readutf(); FileUtility.trasferisci_a_byte( insock, new DataOutputStream(System.out)); 5. Chiusura della connessione con il client: clientsocket.close(); 6. Chiusura della socket di ascolto: serversocket.close(); Applicazioni Distribuite e Servizi di Rete Java socket stream - 5 Applicazioni Distribuite e Servizi di Rete Java socket stream - 6
FileUtility public class FileUtility static protected void trasferisci_a_byte( DataInputStream src, DataOutputStream dest) throws IOException // ciclo di lettura da sorgente // e scrittura su destinazione byte buffer=0; int val=0; try while ((buffer=src.readbyte())!= -1) dest.writebyte(buffer); catch(eofexception e) dest.writebyte(-1); dest.flush(); PutFile Client public class PutFileClient public static void main(string[] args) throws IOException InetAddress addr=null; Socket socket=null; DataInputStream infile=null; DataOutputStream outsock=null; // determinazione indirizzo server try if (args.length == 0) addr = InetAddress.getByName(null); else addr = InetAddress.getByName(args[0]); catch(unknownhostexception e) System.exit(1); // creazione stream di input da tastiera BufferedReader stdin = new BufferedReader( new InputStreamReader(System.in)); try while (stdin.readline()!=null) // richiesta dati da utente try System.out.print("Nome file (estensione)? "); nomefile = stdin.readline(); catch (Exception e) // se la richiesta è corretta creo socket e stream if (nomefile.equals("*") (new File(nomeFile)).exists()) // creazione socket try socket = new Socket( addr, PutFileServerSeq.PORT); socket.setsotimeout(30000); catch (Exception e) Applicazioni Distribuite e Servizi di Rete Java socket stream - 7 Applicazioni Distribuite e Servizi di Rete Java socket stream - 8
// creazione stream di output su socket try outsock = new DataOutputStream(socket.getOutputStream()); catch(ioexception e) // se la richiesta non è corretta non proseguo else System.out.println("File non presente nel direttorio corrente"); /* la richiesta è corretta caso "*": invio di tutti i file.txt del direttorio corrente*/ if (nomefile.equals("*")) File f = new File("."); String[] listafile = f.list(); for (int i=0; i<listafile.length; i++) if (listafile[i].endswith(".txt")) // creazione stream di input da file try infile = new DataInputStream( new FileInputStream(listaFile[i])); catch(filenotfoundexception e) outsock.writeutf(null); Applicazioni Distribuite e Servizi di Rete Java socket stream - 9 // trasmissione del nome try outsock.writeutf(listafile[i]); catch(exception e) // trasmissione del file try FileUtility.trasferisci_a_byte( infile, outsock); catch(exception e) // if.txt // for // if "*" /* caso di un nome specifico invio solo del file richiesto */ else // creazione stream di input da file try infile = new DataInputStream( new FileInputStream(nomeFile)); catch(filenotfoundexception e) // trasmissione del nome tryoutsock.writeutf(nomefile); catch(exception e) Applicazioni Distribuite e Servizi di Rete Java socket stream - 10
// trasmissione del file try FileUtility.trasferisci_a_byte( infile, outsock); catch(exception e) // else // tutto ok, pronto per nuova richiesta System.out.print("\n^D(Unix)/^Z(Win)+invio per uscire, solo invio per continuare: "); // while /* qui catturo le eccezioni non gestite nel while: per esempio la chiusura della connessione con il server in seguito alle quali il client termina l'esecuzione */ catch(exception e) stdin.close(); PutFile Server Sequenziale public class PutFileServerSeq public static final int PORT = 1050; public static void main(string[] args) throws IOException ServerSocket serversocket = null; Socket clientsocket=null; DataInputStream insock=null; try serversocket = new ServerSocket(PORT); serversocket.setreuseaddress(true); catch(exception e) System.exit(1); try while(true) System.out.println("\n In attesa di richieste..."); try clientsocket = serversocket.accept(); clientsocket.setsotimeout(30000); catch (Exception e) Applicazioni Distribuite e Servizi di Rete Java socket stream - 11 Applicazioni Distribuite e Servizi di Rete Java socket stream - 12
try // creazione stream di input da socket insock = new DataInputStream( clientsocket.getinputstream()); catch(ioexception e) String nomefile; while (clientsocket.isconnected()) /* qui catturo le eccezioni non gestite all'interno del while in seguito alle quali il server termina l'esecuzione */ catch(exception e) // chiusura di stream e socket // SOLO IN CASO DI PROBLEMI clientsocket.close(); serversocket.close(); // ricezione del nome try nomefile=insock.readutf(); catch(exception e) break; //ciclo di ricezione dal client e scrittura su video try FileUtility.trasferisci_a_byte( insock, new DataOutputStream(System.out)); catch(exception e) clientsocket.close(); break; clientsocket.close(); // while (true) Applicazioni Distribuite e Servizi di Rete Java socket stream - 13 Applicazioni Distribuite e Servizi di Rete Java socket stream - 14
PutFile Server Concorrente /* Thread lanciato per ogni richiesta accettata */ class ServerThread extends Thread private static int counter=0; private int id=++counter; private Socket socket; private DataInputStream insock=null; // costruttore public ServerThread(Socket s) throws Exception socket=s; try // creazione stream di input da socket insock = new DataInputStream(socket.getInputStream()); catch(ioexception e) throw e; /* se tutto ok il thread viene avviato direttamente dal costruttore */ if (insock!=null) start(); // costruttore public void run() try while (socket.isconnected()) String nomefile; // ricezione del nome. //ciclo di ricezione dal client e scrittura su video try FileUtility.trasferisci_a_byte( insock, new DataOutputStream(System.out)); catch(exception e) break; // while (socket.isconnected()) catch(exception e) // run // ServerThread public class PutFileServerCon public static final int PORT = 1050; public static void main(string[] args) Applicazioni Distribuite e Servizi di Rete Java socket stream - 15 Applicazioni Distribuite e Servizi di Rete Java socket stream - 16
throws IOException ServerSocket serversocket = null; Socket clientsocket=null; try serversocket = new ServerSocket(PORT); serversocket.setreuseaddress(true); catch(exception e) System.exit(1); try while(true) System.out.println("Server: in attesa di richieste...\n"); try // bloccante finchè non arriva una // richiesta di connessione clientsocket = serversocket.accept(); clientsocket.setsotimeout(60000); catch (Exception e) e.getmessage()); // servizio delegato ad un nuovo thread try new ServerThread(clientSocket); catch (Exception e) Applicazioni Distribuite e Servizi di Rete Java socket stream - 17 // while true /* qui catturo le eccezioni non gestite all'interno del while in seguito alle quali il server termina l'esecuzione */ catch(exception e) // chiusura di socket di accettazione serversocket.close(); Applicazioni Distribuite e Servizi di Rete Java socket stream - 18