Category: programação distribuída
aula5TProxy
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; class ClientHanlder extends Thread { Socket sockIn; Socket sockOut; public ClientHanlder(Socket s1, Socket s2) { sockIn = s1; sockOut = s2; } @Override public void run() { int c; System.out.println(Thread.currentThread().getName() + " iniciada."); try { InputStream in = sockIn.getInputStream(); OutputStream out = sockOut.getOutputStream(); while ((c = in.read()) != -1) { out.write(c); } } catch (IOException e) { System.out.println(Thread.currentThread().getName() + " : " + e); } finally { try { sockIn.close(); } catch (Exception e) { } try { sockOut.close(); } catch (Exception e) { } } } } class Proxy { static final int LISTENING_PORT = 5001; static final String POP_ADR = "pop.isec.pt"; static final int POP_PORT = 110; private int listeningPort; private int destinationPort; private String destinationAddr; ServerSocket listeningSocket; public Proxy() { listeningPort = -1; destinationAddr = null; destinationPort = -1; } public void processArguments(String args[]) { if (args.length == 3) { try { listeningPort = Integer.parseInt(args[0]); destinationAddr = args[1]; destinationPort = Integer.parseInt(args[2]); } catch (NumberFormatException e) { listeningPort = -1; } } if (listeningPort == -1) { listeningPort = LISTENING_PORT; destinationAddr = POP_ADR; destinationPort = POP_PORT; } } public void processaPedidos(String args[]) throws IOException { Socket cliScket, socketToPopServer; Thread t1, t2; processArguments(args); System.out.println("porto de escuta: " + listeningPort + " ; destino " + destinationAddr + " ; Porto de destino: " + destinationPort); while (true) { cliScket = listeningSocket.accept(); System.out.println("Novo cliente: " + cliScket.getInetAddress().getHostName() + ":" + cliScket.getPort()); try { socketToPopServer = new Socket(destinationAddr, destinationPort); } catch (IOException e) { System.out.println(e); cliScket.close(); continue; } t1 = new ClientHanlder(socketToPopServer, cliScket); t2 = new ClientHanlder(cliScket, socketToPopServer); t1.setName("Thread " + socketToPopServer.getInetAddress().getHostAddress() + ":" + socketToPopServer.getPort() + "->" + cliScket.getInetAddress().getHostAddress() + ":" + cliScket.getPort() + "]"); t2.setName("Thread " + socketToPopServer.getInetAddress().getHostAddress() + ":" + socketToPopServer.getPort() + "->" + cliScket.getInetAddress().getHostAddress() + ":" + cliScket.getPort() + "]"); t1.start(); t2.start(); } } } public class aula05TProxy { public static void main(String[] args) throws IOException { Proxy p; p = new Proxy(); p.processaPedidos(args); } }
aula5TJDBC
import java.sql.*; class aula5TJDBC { static final String JDBC_DRIVEr = "com.mysql.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost/pd"; static final String USER = "root"; static final String PASS = ""; static final String QUERY = "SELECT * FROM testepd"; public static void main(String[] args) { // Open a connection Connection conn = null; Statement stmt = null; ResultSet rs = null; try { Class.forName("com.mysql.cj.jdbc.Driver"); System.out.println("Ligar à base de dados.."); conn = DriverManager.getConnection(DB_URL, USER, PASS); System.out.println("Concretizar uma operação.."); stmt = conn.createStatement(); String sql = "SELECT * FROM testepd;"; rs = stmt.executeQuery(sql); while (rs.next()) { int id = rs.getInt("id"); String nome = rs.getString("nome"); String localidade = rs.getString("localidade"); int idade = rs.getInt("idade"); System.out.print("ID: " + id); System.out.print(", nome: " + nome); System.out.print(", localidade: " + localidade); System.out.println(", idade: " + idade); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { try{ if(stmt != null){ stmt.close(); } } catch (SQLException e) { e.printStackTrace(); } try{ if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); } try{ if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); } } System.out.println("Terminou"); } } //versão google /* import java.sql.*; public class FirstExample { static final String DB_URL = "jdbc:mysql://localhost/pd"; static final String USER = "root"; static final String PASS = ""; static final String QUERY = "SELECT * FROM testepd"; public static void main(String[] args) { // Open a connection try(Connection conn = DriverManager.getConnection(DB_URL, USER, PASS); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(QUERY);) { // Extract data from result set while (rs.next()) { // Retrieve by column name System.out.print("ID: " + rs.getInt("id")); System.out.print(", nome: " + rs.getString("nome")); System.out.print(", localidade: " + rs.getString("localidade")); System.out.println(", idade: " + rs.getInt("idade")); } } catch (SQLException e) { e.printStackTrace(); } } } */
aula11tRESTApi
Aula11tRestApiApplication.java
package pd.aula11tRESTApi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Aula11tRestApiApplication { public static void main(String[] args) { SpringApplication.run(Aula11tRestApiApplication.class, args); } }
Country.java
package pd.aula11tRESTApi; public class Country { private String nome; private int population; public Country(String nome, int population) { this.nome = nome; this.population = population; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public int getPopulation() { return population; } public void setPopulation(int population) { this.population = population; } }
HelloWorld.java
package pd.aula11tRESTApi; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("hello-world") public class HelloWorld { //http://localhost:8080/hello-world?name=pedro //curl -i http://localhost:8080/hello-world?name=pedro /* //v1 @GetMapping("") public String get1(@RequestParam(value="name", required = false)String req_name){ if(req_name != null){ return "Hello " + req_name + "!"; }else{ return "Hello world"; } } @GetMapping("{name}") public String get2(@PathVariable("name") String provided_name){ return "Hello " + provided_name + "!"; } */ /* //v2 @GetMapping(value = {"","{name}"}) public String get1(@RequestParam(value="name", required = false)String req_name, @PathVariable(value = "name", required = false) String path_name){ if(path_name != null){ return "Hello " + path_name + "!"; }else if(req_name != null){ return "Hello " + req_name + "!"; }else{ return "Hello world"; } } */ }
HelloWorldDB.java
package pd.aula11tRESTApi; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; public class HelloWorldDB { @GetMapping("world/countries") public List<String> getCountries(@RequestParam(value="name", required=false) String name, @RequestParam(value="min-pop", required=false) String min_population) throws SQLException { List<String> countries = new ArrayList<>(); try( Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/world", "root", ""); Statement st = conn.createStatement()){ String query = "select name, population from country"; if(name!=null){ query += " where name like '%" + name +"%'"; if (min_population!=null){ query += " and population>=" + min_population; } }else if(min_population!=null){ query += " where population>=" + min_population; } ResultSet rs = st.executeQuery(query); while(rs.next()){ countries.add(rs.getString("name")); } }catch(SQLException ex){ System.out.println(ex); throw ex; } return countries; } @GetMapping("world/countries/{name}") public ResponseEntity getCountries(@PathVariable("name") String name){ Country result; try( Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/world", "root", ""); Statement st = conn.createStatement()){ String query = "select name, population from country where name='"+name+"'"; ResultSet rs = st.executeQuery(query); if(rs.next()){ result = new Country(rs.getString("name"), rs.getInt("population")); }else{ return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Country " + name + " not found!"); } }catch(SQLException ex){ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.toString()); } return ResponseEntity.status(HttpStatus.OK).body(result); } }
aula10Thttp
fetchURL.java
import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; class FetchURL { /* public static void main(String args[]) throws Exception { int argc = args.length; if (argc != 1){ System.out.println ("Syntax: java FetchURL url"); return; } try { URL myURL = new URL( args[0] ); InputStream in = myURL.openStream(); BufferedInputStream bufIn = new BufferedInputStream(in); while((data = bufIn.read())!= -1){ //!EOF System.out.print ((char)data); } System.out.println ("\nHit <Enter> to continue"); System.in.read(); }catch (MalformedURLException e){ System.err.println ("Unable to parse URL!"); return; }catch (IOException ioe){ System.err.println ("I/O Error : " + ioe); return; } } */ }
SingleQuoteConsumer.java
import java.io.*; import java.net.*; import com.google.gson.*; import javax.json.*; public class SingleQuoteConsumer { public static void main(String args[]) throws MalformedURLException, IOException { String quoteId = args.length >0 ? args[0] : "random"; getQuoteFromQuoteService(quoteId); } public static void getQuoteFromQuoteService(String quoteId) throws MalformedURLException, IOException { String uri = "http://gturnquist-quoters.cfapps.io/api/"+quoteId; URL url = new URL(uri); HttpURLConnection connection; connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Accept", "application/xml, */*"); InputStream in = connection.getInputStream(); JsonReader jsonReader = Json.createReader(in); JsonObject object = jsonReader.readObject(); jsonReader.close(); connection.disconnect(); Gson gson = new GsonBuilder().create(); Quote q = gson.fromJson(object.toString(), Quote.class); System.out.println("Tipo: " + q.getType()); System.out.println("Id: " + q.getValue().getId()); System.out.println("Citacao: " + q.getValue().getQuote()); } }
url.java
import java.net.MalformedURLException; import java.net.URL; public class url { public static void main(String args[]) { int argc = args.length; if (argc != 1){ System.out.println ("Syntax : java URLParser url "); return; } try { URL myURL = new URL( args[0] ); System.out.println ("Protocol : " + myURL.getProtocol() ); System.out.println ("Hostname : " + myURL.getHost() ); System.out.println ("Port : " + myURL.getPort() ); System.out.println ("Filename : " + myURL.getFile() ); }catch (MalformedURLException e){ System.err.println ("Unable to parse URL!"); return; } } }
URLConnection.java
import java.net.*; import java.io.*; public class URLConnection { public static void main(String args[]) throws Exception { int argc = args.length; if (argc != 1) { System.out.println("Syntax: java FetchURLConnection url"); return; } try { java.net.URL myURL = new URL(args[0]); URLConnection connection = myURL.openConnection(); connection.connect(); // DISPLAY THE MIME CONTENT-TYPE (E.G. TEXT/HTML) String MIME = ((java.net.URLConnection) connection).getContentType(); System.out.println("Content-type: " + MIME); // DISPLAY, IF AVAILABLE, THE CONTENT LENGTH int contentLength = connection.getContentLength(); if (contentLength != -1) { System.out.println("Content-length: " + contentLength); } // Pause for user System.out.println("Hit enter to continue"); System.in.read(); // READ THE CONTENTS OF THE RESOURCE FROM THE CONNECTION InputStream in = connection.getInputStream(); // BUFFER THE STREAM, FOR BETTER PERFORMANCE BufferedInputStream bufIn = new BufferedInputStream(in); while ((data = bufIn.read()) > 0) { System.out.print((char) data); } } catch (MalformedURLException e) { System.err.println("Unable to parse URL!"); return; } catch (IOException e) { System.err.println("I/O Error : " + ioe); return; } } }
aula08tRMICallbacks
TemperatureListener.java
import java.rmi.Remote; import java.rmi.RemoteException; //A interface remota associada aos listeners define apenas o método temperatureChanged() interface TemperatureListener extends Remote { public void temperatureChanged(double temperature) throws RemoteException; }
TemperatureMonitorCliente.java
import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; //Monitor de mudança de temperatura (listener) public class TemperatureMonitorCliente extends UnicastRemoteObject implements TemperatureListener { public TemperatureMonitorCliente() throws RemoteException { // NO CODE REQUIRED //nao precisamos do construtor mas todos os serviços RMi precisam por causa do throws RemoteException } public static void main(String args[]) { System.out.println("Looking for temperature sensor"); // ONLY REQUIRED FOR DYNAMIC CLASS LOADING // SYSTEM.SETSECURITYMANAGER ( NEW RMISECURITYMANAGER() ); try { String registry = "localhost"; if (args.length >= 1) { registry = args[0]; } // LOOKUP THE SERVICE IN THE REGISTRY, AND OBTAIN A REMOTE SERVICE String registration = "rmi://" + registry + "/TemperatureSensor"; Remote remoteService = Naming.lookup(registration); TemperatureSensor sensor = (TemperatureSensor) remoteService; // GET AND DISPLAY CURRENT TEMPERATURE double reading = sensor.getTemperature(); System.out.println("Original temp : " + reading); // CREATE A NEW MONITOR AND REGISTER IT AS A LISTENER WITH REMOTE SENSOR TemperatureMonitorCliente monitor = new TemperatureMonitorCliente(); //criar o serviço sensor.addTemperatureListener(monitor); //registo o sensor } catch (NotBoundException e) { System.out.println("No sensors available"); } catch (RemoteException e) { System.out.println("RMI Error - " + e); } catch (Exception e) { System.out.println("Error - " + e); } } //MAIN public void temperatureChanged(double temperature) throws java.rmi.RemoteException { System.out.println("Temperature change event : " + temperature); } }
TemperatureSensor.java
//Interface associada ao serviço de medição de temperatura (i.e., fonte do evento mudança de temperatura) interface TemperatureSensor extends java.rmi.Remote { public double getTemperature() throws java.rmi.RemoteException; public void addTemperatureListener(TemperatureListener listener) throws java.rmi.RemoteException; public void removeTemperatureListener(TemperatureListener listener) throws java.rmi.RemoteException; }
TemperatureSensorServer.java
import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import java.util.List; import java.util.Random; //Serviço + Servidor sensor de temperatura public class TemperatureSensorServer extends UnicastRemoteObject implements TemperatureSensor, Runnable { private volatile double temp; //THE VALUE OF THIS VARIABLE WILL NEVER BE //CACHED THREAD-LOCALLY private List<TemperatureListener> list; public TemperatureSensorServer() throws java.rmi.RemoteException { temp = 20.0; list = new ArrayList<TemperatureListener>(); } //parte de comunicação gerada autmaticamente public synchronized double getTemperature() throws java.rmi.RemoteException { return temp; } public synchronized void addTemperatureListener(TemperatureListener listener) throws RemoteException { System.out.println("adding listener -" + listener); list.add(listener); } public synchronized void removeTemperatureListener(TemperatureListener listener) throws java.rmi.RemoteException { System.out.println("removing listener -" + listener); list.remove(listener); } public synchronized void changeTemp(Random r) { int num = r.nextInt(); if (num < 0) temp += 0.5; else temp -= 0.5; // NOTIFY REGISTERED LISTENERS notifyListeners(); } //run é acessorio public void run() { Random r = new Random(); while (true) { try { // SLEEP FOR A RANDOM AMOUNT OF TIME int duration = r.nextInt() % 10000 + 2000; if (duration < 0) duration = -1 * duration; Thread.sleep(duration); } catch (InterruptedException e) { } // COMPUTE NEW VALUE FOR TEMP changeTemp(r); } } //WHILE private synchronized void notifyListeners() { for (int i = 0; i < list.size(); i++) { TemperatureListener listener = list.get(i); try { listener.temperatureChanged(temp); //temperatureChanged vai ser executado do lado do cliente } catch (RemoteException e) { //UNABLE TO CONTACT LISTENER System.out.println("removing listener -" + listener); list.remove(listener); i--; } } } public static void main(String args[]) { System.out.println("Loading temperature service"); // ONLY REQUIRED FOR DYNAMIC CLASS LOADING //System.setSecurityManager ( new RMISecurityManager() ); try { // LOAD THE SERVICE TemperatureSensorServer sensor = new TemperatureSensorServer(); //criar o serviço // REGISTER WITH SERVICE SO THAT CLIENTS CAN FIND US String registry = "localhost"; if (args.length >= 1) { registry = args[0]; } String registration = "rmi://" + registry + "/TemperatureSensor"; Naming.rebind(registration, sensor); //referencia remota ficar registada no registry //para os clientes depois obterem essa referencia remota // CREATE A THREAD TO TRIGGER REGULAR TEMPERATURE CHANGES //serve apenas para simular as diferentes temperaturas Thread thread = new Thread(sensor); thread.start(); } catch (RemoteException re) { System.err.println("Remote Error - " + re); } catch (Exception e) { System.err.println("Error - " + e); } } //MAIN }
aula07tRMi
clienteRMi.java
import java.rmi.*; public class clienteRMi { public static void main(String args[]) { System.out.println ("Looking for light bulb service"); try { String registry = "localhost"; if (args.length >=1){ registry = args[0]; } String registration = "rmi://" + registry + "/registryRMInterfaceRemotaImplements"; Remote remoteService = Naming.lookup ( registration ); //cria a ligação TCP // CAST TO A RMILIGHTBULB INTERFACE registryRMInterfaceRemota bulbService = (registryRMInterfaceRemota) remoteService; //fazemos o cast para aceder aos métodos da interface bulbService.on(); System.out.println ("Bulb state : " + bulbService.isOn() ); bulbService.off(); System.out.println ("Bulb state : " + bulbService.isOn() ); }catch (NotBoundException e){ System.out.println ("No light bulb service available!"); }catch (RemoteException e){ System.out.println ("RMI Error - " + e); }catch (Exception e){ System.out.println ("Error - " + e); } } }
registryRMInterfaceRemota.java
//Interfaces Remotas public interface registryRMInterfaceRemota extends java.rmi.Remote { public void on() throws java.rmi.RemoteException; public void off() throws java.rmi.RemoteException; public boolean isOn() throws java.rmi.RemoteException; }
registryRMInterfaceRemoteImplements.java
//implements //public class registryRMInterfaceRemoteImplements extends java.rmi.server.UnicastRemoteObject implements registryRMInterfaceRemota public class registryRMInterfaceRemoteImplements extends java.rmi.server.UnicastRemoteObject implements registryRMInterfaceRemota { private boolean lightOn; // A CONSTRUCTOR MUST BE PROVIDED FOR THE REMOTE OBJECT public registryRMInterfaceRemoteImplements() throws java.rmi.RemoteException { setBulb(false); } // REMOTELY ACCESSIBLE "ON" METHOD - TURNS ON THE LIGHT public void on() throws java.rmi.RemoteException { setBulb(true); } public void off() throws java.rmi.RemoteException { setBulb (false); } public boolean isOn() throws java.rmi.RemoteException { return getBulb(); } public void setBulb (boolean value) { lightOn = value; } public boolean getBulb () { return lightOn; } }
RMIServer.java
import java.rmi.*; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.*; public class RMIServer { public static void main(String args[]) { System.out.println ("Loading RMI service"); System.out.println ("Loading RMI service"); try { //v1 // LOAD THE SERVICE registryRMInterfaceRemoteImplements bulbService = new registryRMInterfaceRemoteImplements(); // EXAMINE THE SERVICE TO SEE WHERE IT IS STORED RemoteRef location = bulbService.getRef(); System.out.println (location.remoteToString()); //v2 Registry r1; try { r1 = LocateRegistry.createRegistry(Registry.REGISTRY_PORT); //HOST LOCAL }catch (RemoteException e) { System.out.println("jรก existe" + e); e.printStackTrace(); r1 = LocateRegistry.getRegistry(); } r1.rebind("registryRMInterfaceRemotaImplements", bulbService); Registry r2 = LocateRegistry.getRegistry(Registry.REGISTRY_PORT); r2.rebind("registryRMInterfaceRemotaImplements", new registryRMInterfaceRemoteImplements()); /* //v1 // CHECK TO SEE IF A REGISTRY WAS SPECIFIED String registry = "localhost"; if (args.length >= 1){ registry = args[0]; } // REGISTRATION FORMAT: //REGISTRY_HOSTNAME[:PORT]/SERVICE_NAME String registration = "rmi://" + registry + "/RMILightBulb"; // REGISTER WITH SERVICE SO THAT CLIENTS CAN FIND US // AN ALREADY REGISTERED SERVICE WILL BE REPLACED Naming.rebind( registration, bulbService ); */ }catch (RemoteException e){ System.err.println ("Remote Error - " + e); }catch (Exception e){ System.err.println ("Error - " + e); } } }
aula05ThreadsMultiplasParalelas
class ParallelPi extends Thread { private int myId, nThreads, nIntervals, myIntervals; private double dX; private double myResult; public ParallelPi(int myId, int nThreads, int nIntervals) { this.myId = myId; this.nThreads = nThreads; this.nIntervals = nIntervals; //calculo do uso da largura dX = 1.0 / (double) nIntervals; myResult = 0; myIntervals = 0; } public double getMyResult() { return myResult; } public int getMyIntervals() { return myIntervals; } //o que a thread executa @Override public void run() { double i, xi; myResult = 0; //verificações relacionadas com as threadas e ids das threads if (nIntervals < 1 || nThreads < 1 || myId < 1 || myId > nThreads) { return; } for (i = myId - 1; i < nIntervals; i += nThreads) { xi = dX * (i + 0.5); myResult += (4.0 / (1.0 + xi * xi)); myIntervals++; } myResult *= dX; } } public class aula05ThreadsMultiplasParalelas { public static void main(String[] args) throws InterruptedException { ParallelPi[] t; //Working threads int i, nThreads; long nIntervals; double pi = 0.0; if (args.length != 2) { System.out.println("Sintaxe: java ParallelPi <número de intervalos > < número de threads>"); return; } nIntervals = Integer.parseInt(args[0]); nThreads = Integer.parseInt(args[1]); t = new ParallelPi[nThreads]; for (i = 0; i < nThreads; i++) { t[i] = new ParallelPi(i + 1, nThreads, (int) nIntervals); t[i].start(); } pi = 0; for (i = 0; i < nThreads; i++) { t[i].join(); pi += t[i].getMyResult(); } System.out.println("Valor aproximado de pi: " + pi); } //main } //class ParallelPi
aula04TSincronizacaoII
//java -cp . aula04TSincronizacaoII class SynchBlock implements Runnable { // A STRING WHICH CAN BE MODIFIED. // ACCESS TO BUFFER AIMS AT BEING SYNCHRONIZED // WITHOUT MODIFYING STRINGBUFFER. StringBuffer buffer; //acumulador int counter; public SynchBlock() { buffer = new StringBuffer(); counter = 1; } //a thread public void run() { // { //sem sincronized synchronized (buffer) { // sincronização.. System.out.println("Starting synchronized block [ "+ Thread.currentThread().getName() +"]"); int tempVariable = counter++; //variavel temp= 0, mas o counter=1 // CREATE MESSAGE TO ADD TO BUFFER, INCLUDING LINE FEED String message = "Count value is : " + tempVariable + System.lineSeparator(); try { // SIMULATE TIME NEEDED FOR SOME TASK Thread.sleep(100); } catch (InterruptedException ie) { } buffer.append(message); System.out.println("... ending synchronized block "+ Thread.currentThread().getName() +"]"); } } } //java -cp . aula04TSincronizacaoII public class aula04TSincronizacaoII { public static void main(String args[]) throws Exception { // CREATE A NEW RUNNABLE INSTANCE SynchBlock block = new SynchBlock(); Thread t1 = new Thread(block); Thread t2 = new Thread(block); Thread t3 = new Thread(block); Thread t4 = new Thread(block); t1.start(); t2.start(); t3.start(); t4.start(); // WAIT FOR ALL THREE THREADS TO FINISH t1.join(); t2.join(); t3.join(); t4.join(); // COUNT SHOULD APPEAR IN THE CORRECT ORDER System.out.println(block.buffer); } }
aula04TSincronizacao
class Counter { private int countValue; public Counter() { countValue = 0; } public Counter(int start) { countValue = start; } //public void increaseCount() { public synchronized void increaseCount() { int count = countValue; // SIMULATE SLOW DATA PROCESSING AND MODIFICATION. // REMOVE THE SYNCHRONIZED KEYWORD AND SEE WHAT HAPPENS... try { Thread.sleep(5); } catch (InterruptedException ie) { } count = count + 1; countValue = count; System.out.println("<" + Thread.currentThread().getName() + " >: cout = " + countValue); } public synchronized int getCount() { return countValue; } } class CountingThread implements Runnable { Counter myCounter; int countAmount; // CONSTRUCT A COUNTING THREAD TO USE THE SPECIFIED COUNTER public CountingThread(Counter counter, int amount) { myCounter = counter; countAmount = amount; } public void run() { // INCREASE THE COUNTER THE SPECIFIED NUMBER OF TIMES for (int i = 1; i <= countAmount; i++) { // INCREASE THE COUNTER myCounter.increaseCount(); //SYNCHRONIZED METHOD } } } public class aula04TSincronizacao { public static void main(String[] args) throws InterruptedException { // CREATE A NEW, THREAD-SAFE COUNTER Counter c = new Counter(); // OUR RUNNABLE INSTANCE WILL INCREASE THE COUNTER // TEN TIMES, FOR EACH THREAD THAT RUNS IT Runnable runner = new CountingThread(c, 10); System.out.println("Starting counting threads"); Thread t1 = new Thread(runner); Thread t2 = new Thread(runner); Thread t3 = new Thread(runner); t1.start(); t2.start(); t3.start(); // WAIT FOR ALL THREE THREADS TO FINISH t1.join(); t2.join(); t3.join(); //aguardo que as threads terminem System.out.println("Counter value is " + c.getCount()); } }
aula04ThreadsComunicacao
public class aula04ThreadsComunicacao extends Thread{ public static void main(String args[]) throws Exception { // START THE ADDITIONAL NEW THREAD THE MAIN THREAD WILL BE AINTING FOR. Thread notificationThread = new aula04ThreadsComunicacao(); notificationThread.start(); // WAIT FOR THE NOTIFICATION THREAD TO TRIGGER EVENT synchronized (notificationThread){ notificationThread.wait(); } // NOTIFY USER THAT THE WAIT() METHOD HAS RETURNED System.out.println ("The wait is over"); } public void run() { //THIS IS THE ADDITONAL THREAD WHICH WAS CREATED+STARTED BY THE MAIN THREAD System.out.println ("Hit enter to stop waiting thread"); try { System.in.read(); }catch (java.io.IOException e){} // NOTIFY ANY THREADS WAITING ON THIS THREAD synchronized (this){ this.notifyAll(); } } }
aula03TPararThreads
import java.io.IOException; class StopMe extends Thread { private boolean stopRunning = false; public void setStop(boolean stopRunning) { this.stopRunning = stopRunning; } public void run() { int count = 1; System.out.println("I can count. Watch me go!"); for (; ; ) { if (stopRunning) return; System.out.print(count++ + " "); try { Thread.sleep(500); } catch (InterruptedException e) { } } } } //sem forçar a terminar uma thread, abordagem correta public class aula03PararThreads { public static void main(String[] args) throws IOException { Thread counter = new StopMe(); counter.start(); System.out.println ("Press any enter to stop the thread counting"); System.in.read(); ((StopMe) counter).setStop(true); } }
aula03ThreadSleepy
class SleepyHead extends Thread { // RUN METHOD IS EXECUTED WHEN THREAD FIRST STARTED public void run() { System.out.println("I feel sleepy. Wake me in eight hours"); try { // SLEEP FOR EIGHT HOURS Thread.sleep(1000 * 60 * 60 * 8); System.out.println("That was a nice nap"); } catch (InterruptedException e) { System.err.println("Just five more minutes...."); } } } public class aula03ThreadSleepy { public static void main(String args[]) throws java.io.IOException { // CREATE A 'SLEEPY' THREAD Thread sleepy = new SleepyHead(); // START THREAD SLEEPING sleepy.start(); // PROMPT USER AND WAIT FOR INPUT System.out.println("Press enter to interrupt the thread"); System.in.read(); // INTERRUPT THE THREAD (DEPRECATED: TO SAFELY TERMINATE A THREAD LET IT DIE // OR MAKE IT EXIT ITS METHOD RUN()) sleepy.interrupt(); //RESUME() METHOD TO RESUME THE THREAD } }
Aula03ThreadII
class RunnableThreadDemo implements java.lang.Runnable { // RUN METHOD IS EXECUTED WHEN THREAD FIRST STARTED public void run() { System.out.println("I am an instance of the java.lang.Runnable interface "); } } public class aula03ThreadII { public static void main(String[] args) { System.out.println("Creating runnable object"); // CREATE RUNNABLE OBJECT Runnable run = new RunnableThreadDemo(); // CREATE A THREAD, AND PASS THE RUNNABLE OBJECT System.out.println("Creating first thread"); Thread t1 = new Thread(run, "Thread 1"); // CREATE A SECOND THREAD, AND PASS THE RUNNABLE OBJECT System.out.println("Creating second thread"); Thread t2 = new Thread(run, "Thread 2"); // START BOTH THREADS System.out.println("Starting both threads"); t1.start(); t2.start(); } }
aula02TCliente
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; //ligação TCP public class aula02TCliente { public static final int SERVICE_PORT = 5001; static Socket daytime = null; public static void main(String args[]) throws IOException { if (args.length != 1){ System.out.println ("Syntax – java DaytimeClient host"); return; } // GET THE HOSTNAME OF SERVER String hostname = args[0]; try { daytime = new Socket (hostname, SERVICE_PORT); System.out.println ("Connection established"); // SET THE SOCKET OPTION JUST IN CASE SERVER STALLS daytime.setSoTimeout( 2000 ); //ms // READ FROM THE SERVER BufferedReader reader = new BufferedReader(new InputStreamReader(daytime.getInputStream())); System.out.println ("Results : " + reader.readLine()); //mudança de linha ou receber um socket fechar // CLOSE THE CONNECTION daytime.close(); }catch (IOException e){ //catches also InterruptedIOException System.err.println ("Error " + e); }finally { //fechar o socket se ele for aberto if(daytime == null){ daytime.close(); } } } }
aula01TServidor
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; //destinatário, receptor public class Servidor { public static void main (String args[]) { try { System.out.println("Binding to local port 2000"); // CREATE A DATAGRAM SOCKET, BOUND TO THE SPECIFIC PORT 2000 DatagramSocket socket = new DatagramSocket(2000); // CREATE A DATAGRAM PACKET WITH A MAXIMUM BUFFER OF 256 BYTES DatagramPacket packet = new DatagramPacket(new byte[256], 256); // RECEIVE A PACKET (BY DEFAULT, THIS IS A BLOCKING OPERATION) socket.receive(packet); // DISPLAY PACKET INFORMATION InetAddress remote_addr = packet.getAddress(); System.out.println("Sent by: " + remote_addr.getHostAddress()); System.out.println("Sent from port: " + packet.getPort()); //apenas os bytes que foram copiados packet.getData() String msg = new String(packet.getData(), 0, packet.getLength()); System.out.println(msg); socket.close(); } catch (IOException e) { System.err.println("Error - " + e); } }}
aula01TCliente
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.UnknownHostException; //emissor public class Cliente { public static void main (String args[]){ // CHECK FOR VALID NUMBER OF PARAMETERS int argc = args.length; if (argc != 1){ System.out.println ("Syntax :"); System.out.println ("java PacketSendDemo hostname"); return; } String hostname = args[0]; try{ System.out.println ("Binding to a local port"); // CREATE A DATAGRAM SOCKET, BOUND TO ANY AVAILABLE LOCAL PORT DatagramSocket socket = new DatagramSocket(); System.out.println ("Bound to local port " + socket.getLocalPort()); byte[] barray = "Greetings!".getBytes(); // CREATE A DATAGRAM PACKET, CONTAINING OUR BYTE ARRAY DatagramPacket packet = new DatagramPacket( barray, barray.length ); System.out.println ("Looking up hostname " + hostname ); // LOOKUP THE SPECIFIED HOSTNAME, AND GET AN INETADDRESS InetAddress addr = InetAddress.getByName(hostname); System.out.println ("Hostname resolved as "+addr.getHostAddress()); // ADDRESS PACKET TO SENDER packet.setAddress(addr); // SET PORT NUMBER TO 2000 packet.setPort(2000); // SEND THE PACKET - REMEMBER NO GUARANTEE OF DELIVERY socket.send(packet); System.out.println ("Packet sent!"); }catch (UnknownHostException e){ System.err.println ("Can't find host " + hostname); }catch (IOException e){ System.err.println ("Error - " + e); } } }
resolução de exercícios
#exame 2019-2020 e #exame 2016-2017
Exame da Época Especial – Avaliação prática – P1
==teórica)
1. Diga, justificando, se é correcto afirmar-se que o seguinte método permite apenas copiar o conteúdo de um ficheiro para outro. Se a resposta for negativa, inclua na justificação pelo menos um contra-exemplo.
public static void copy(java.io.InputStream in, java.io.OutputStream out) throws java.io.IOException
{
int c;
while ((c = in.read()) != -1){
out.write(c);
}
}
R:
pode ser usado também para leitura e escrita em sockets
as classes InputStream e OutputStream são classes abstractas, e uma classe abstracta são aquelas em que existe pelo menos um método não implementado
neste exemplo temos um método que recebe dois métodos: InputStream e OutputStream
o InputStream é uma classe abstracta que tem métodos do tipo: read, read só com um caracter, receb arrays de bytes e devolve o numero de bytes copiados, e subarrays, ..
o OutputStream é uma classe abstracta que tem métodos do tipo: tem métodos para escrever, e que permite ir buscar bytes ou um fluxo de bytes, por exemplo no ecrã, num ficheiro, numa ligação TCP, pode ser um array de bytes,..
mas a resposta é não porque são classes abstractas
posso copiar de ficheiro para ficheiro
posso copiar de ficheiro para socket
posso copiar de socket para ficheiro
para teste:
o OutputStream só permite serializar para ficheiro? ou só permite serializar para socket?
r:
não porque ao criar um objecto OutputStream passamos-lhe qualquer coisa que é OutputStream
o que o wirte and share do OutputStream precisa de receber um objecto que implemente os métodos do OutputStream, e não interessa como
para teste:
o que faz o método write object no OutputStream
r:
o write object implementa o algortimo de serialização, pega num objecto, que na realidade é uma arvore de objecto (porque depois temos referências), e o que produz num formato especifico que é um binário java, produz um fluxo de bytes contiguos que permite desctever no objecto as várias classes envolvidas,as versões, os valores, os membros, .., e que permite depois ser transmitido ou guardar
para teste:
o que um driver, o que faz um driver jbdc?
R:
o driver é um conjunto de classes que vamos buscar num jar e que tem classes/métodos que implementam a api do jbdc
o driver é a implementação dessa API, dessas classes, para acesso a servidores de BD especificos
para teste:
R:
porque não posso usar um conector mysql para aceder a uma base de dados de oracle?
têm drivers diferentes, porque muitas das coisas que as classes/métodos fazem é estabelecer uma ligação TCP ao servidor remotamente
e enviar pedidos num determinado formato que tem a ver com o protocolo e os SGBD, e quem desenvolveu o protocolo não desenvolveu nenhum protocolo de comunicação ao nivel a aplicação, entre o cliente o servidor BD, não implemntou de forma standart e por esse motivo as mensagens e as trocas de mensagens são diferentes
==teórica)
2. Geralmente, associado a plataformas de middleware que oferecem a abstracção de objecto remoto/distribuído, existem aplicações que, em termos genéricos, podem ser designadas de serviços de nomeação (por exemplo, rmiregistry.exe, tnamrserv.exe e orbd.exe). Explique quais são os seus dois objectivos principais e de que forma estes são atingidos (ou seja, enumere as principais operações/passos executados desde a fase de arranque). Na resposta, que não deve incluir código, utilize, entre outros, os termos socket, mensagem, porto e thread.
r:
conceito de RMi (ou corba)
estas têm uma aplicação autónoma, mas que têm o mesmo objectivo e que são os serviços de nomeação
rmiregistry (no RMi)
orbd (no Corba)
o rmiregistry
os dois principais objectivos são:
ao inves de saber o ip e o porto automático do servidor, mas eu coloco numa maquina qualquer com o ip conhecido e com porto fixo de 1099,
assim
o servidor quando arranca contacta (ligação TCP) o rmiregistry
e envia uma informação a dizer regista este proxy/este serviço sob este nome
uma aplicação que quer aceder ao serviço contacta o rmiregistry (ligação TCP, no ip e no porto 1099) a pedir o serviço remoto
o rmiregistry faz o lookup e devolve serializado ou envia uma excepção.
a aplicação recebe, tem uma classe, recebe um objecto do tipo, onde tem o ip e o porto da maquina(servidor) onde está o serviço
r2:
dois objectivos:
registar serviços com um determinado nome, referências para objectos remotas sob determinados nomes, e permite obter essas referencias através de queries
e permite obter a referência, isto é, permite fazer um submit e um get
e enumere as principais fazes de arranque:
é um servidor TCP concorrente, que é posto a correr,
e quando quero utilizar o serviço faço uma ligação TCP com a indicação do porto, e é enviado um pedido sobre a forma de uma mensagem
o servidor está à espera de pedidos de ligação, e como é um servidor concorrente, sempre que alguém se liga cria uma thread, aguarda o pedido e responde
(lembrar que só existe uma forma de comunicar na internet, e é através de sockets)
para teste:
o que faz, qual o objectivo este método estático e o que é desencadeado quando o chamam:
Naming.bind(“rmi://192.168.1.1/nome1”, o);
objetivo: solicitar a uma aplicação rmi, que está a correr na maquina com o ip 192.168.1.1, com o porto 1099, e enviar-lhe o registo do serviço/referencia remoto o, com o nome nome1
estabelece um ligação TCP, e enviar-lhe uma mensagem, com o regista-me aí um serviço RMi com o nome nome1, e também toma a referência serializada o
se correr bem ele acrescenta
se correr mal ou se já existir ele lança uma excepção
e ele envia uma resposta (uma excepção ou um true ou um false)
para teste:
Naming.rebind(“rmi://192.168.1.1/nome1”, o);
para teste:
o que faz, qual o objectivo este método estático e o que é desencadeado quando o chamam:
Naming.lookup(“rmi://192.168.1.1/nome2″);
contactar uma aplicação Rmi registry que está no ip 192.168.1.1, na porta 1099, de qualquer coisa que ele tem com o nome nome2
estabelece um ligação TCP, no ip e no porto
constroi uma mensagem que obtem a referencia para o nome2
serializa a mensagem, através da ligação TCP
do outro lado o registry vai receber a mensagem, e verifca se corre bem, se encontra, e devolver o resultado
e quando se recebe a mensagem desserializa-a e vê a resposta, e com base na resposta devolve a referencia remota ou lança uma excepção
==teórica)
3.Diga qual é o objectivo do seguinte método e descreva o significado de cada um dos campos que compõem a URL passada como argumento (rmi, 192.168.1.1, 1099 e RMILightBulb):
java.rmi.Remote r = java.rmi.Naming.lookup(“rmi://192.168.1.1:1099/RMILightBulb”).
r:
o objecto é obter uma referencia remota para o objecto que está registado no rmiregistry com o nome RMILightBulb
rmi, é o protocolo usado na comunicação, é o que define as mensagens trocadas entre a aplicação que chama isto e a aplicação do outro lado
192.168.1.1, é o ip onde está a correr o rmiregistry
1099, é o porto onde está a correr o rmiregistry
RMILightBulb, é o nome do serviço
para teste:
o que é que acontece por baixo com java.rmi.Remote r = java.rmi.Naming.lookup(“rmi://192.168.1.1:1099/RMILightBulb”)?
r:
estabelece uma ligação TCP naqueles ip e porto, envia uma mensagem com um pedido para uma referência remota de um objecto que se chama RMILightBulb e aguarda resposta
se a resposta for um objecto do tipo excepção faz o throw da excepção
caso contrário faz o return do que recebeu e depois temos que fazer o cast
==teórica)
4. O pedaço de código seguinte permite obter um recurso alojado um servidor Web através do protocolo HTTP, recorrendo a uma classe específica que encapsula esse tipo de interacção. Sabendo que o HTTP é um protocolo do nível de aplicação que recorre ao protocolo de transporte TCP e, por imissão, ao porto 80, deduza a sequência de acções/passos principais desencadeados pelo método openStream (1- Estabelece… 2- … m- Envia… n- Obtém… o-
Devolve…). A resposta não deve incluir código.
java.net.URL myURL = new java.net.URL (“https://moodle.isec.pt/moodle/mod/folder/view.php?id=470″);
java.net.InputStream in = myURL.openStream();
int b;
while(true){
b = in.read();
…
}
r:
existe um objecto do tipo:
java.net.URL myURL
depois temos
java.net.InputStream in = myURL.openStream();
e de seguida:
b = in.read();
e com tudo isto estou a receber o conteudo da resposta get que foi enviado para este servidor e para este recursoview.php?id=470
o URL pode dar-me uma excepção
quando se faz o myURL.openStream(), e
estabelece uma ligação TCP nesta maquina (https://moodle.isec.pt/)
envia um pedido get oara identificar como recurso o URI: moodle/mod/folder/view.php?id=470
e do outro lado ele vai enviar uma resposta com várias linhas de texto com vários \n \n e fecha a ligação TCP
no buffer de entrada eu vou ter os bytes enviados, que é a resposta
fica associado ao objecto java.net.InputStream in = myURL.openStream();
e ao fazer o read b = in.read();
vão ser lidos os bytes
==teórica)
5. Acrescente uma única linha de código na classe UseMyThreads ou MyThread de modo a que a thread t2 apenas inicie depois de t1 deixar de estar activa. Altere igualmente a declaração do método metodo1 de modo a que, se várias threads possuírem uma referência para a mesma instância da classe MyThread, este apenas possa ser executado por uma única thread em cada instante.
public class MyThread extends Thread {
X x;
public MyThread(X x){
this.x = x;
}
…
public metodo1(){
…
}
…
public void run() {
…
}
…
}
public class UseMyThreads {
…
public static void main(String args[]){
…
Thread t1 = new MyThread(new X()).start();
Thread t2 = new MyThread(new X()).start();
…
}
}
r:
a Thread t1 = new MyThread(new X()).start();
vai correr o run
assim e no UseMyThreads podemos usar um JOIN
Thread t1 = new MyThread(new X()).start();
t1.join;
r2:
ou até podia olhar para:
assim e no MyThread e no run() podemos fazer
synhcronized(x){…};
mas quando fazermos new MyThread(new X()).start();
estamos a criar objectos novos e não vão bloquear logo esta solução não é válida só seria se
ao invés de:
Thread t1 = new MyThread(new X()).start();
Thread t2 = new MyThread(new X()).start();
e se existir:
declaração de um X = new X
e passar o X para dentro de cada thread este mesmo X
e agora sim vem o synhcronized do X
mas isto tb não é veridico face ao não sabes como vai ser o escalonamento e isso depende do SO
atenção: não é porque no código existe uma sequencia que u output é sempre igual.. as coisas variam face ao escalonamento
r3:
segunda parte da resposta é meter o método 1 como synhcronized
na classe MyThread
public synhcronized metodo1(){ … }
eu posso fazer synhcronized ao nivel do método no run nao posso só internamente
r4 final:
primeira parte:
assim e no UseMyThreads podemos usar um JOIN
Thread t1 = new MyThread(new X()).start();
t1.join;
segunda parte da resposta é meter o método 1 como synhcronized
na classe MyThread
public synhcronized metodo1(){ … }
eu posso fazer synhcronized ao nivel do método no run nao posso só internamente
==teórica) #exame 19-20 especial
1.
considere uma api web (web service) que incluir entre outras s seguintes URI:
1) /users?address=”coimbra”
2) /users/delete?address=”coimbra”
3) /users/coimbra
4) /users/coimbra10
extras
5) /users/10/update?address=”coimbra”
6) /users/insert?id=10&name=”ana”&address=”coimbra”
a) indique para cada uma um possivel significado
r:
1) lista de utilizadores com morada em coimbra
2) manda apagar da lista de utilizadores com a morada em coimbra
3) lista de utilizadores que vivem em coimbra
4) identifica o utilizador com o codigo 10, dos utilizadores que vivem em coimbra OU a 10ª página de utilizadores de coimbra OU o registo 10 em coimbra
extras
5) um pedido de update da morada do utilizador com o codigo 10
6) inserir nos utilizadores com os dados…
b) identifique, justificando a URI que não serve os principios REST e apresente, igualmente uma alternativa que esteja correcta
olhar para as primeiras 4
2) tem um verbo, a URI só deve identificar o recurso a URI correta seria
as URI identificam o recurso, as acções é através de um verbo, que vai na mensagem http
==teórica) #exame 19-20 especial
2)
explique o conceito de callback/notificação assincrona em sistemas distribuidos e de que forma pode conseguir-se esta funcionalidade em aplicações baseadas no paradigma de objecto remoto (e.g JavaRmi). não recorra a código na resposta
explique o conceito de callback/notificação assincrona em sistemas distribuidos e de que forma pode conseguir-se esta funcionalidade em aplicações baseadas em sockets TCP (e.g., instâncias da classe java.net.Socket na linguagem java). não recorra a código na resposta
explique o conceito de callback/notificação assincrona em sistemas distribuidos e de que forma pode conseguir-se esta funcionalidade em aplicações baseadas em sockets UDP (e.g. instâncias da classe java.net.DatagramSocket na lingiagem java). não recorra código na resposta)
==teórica) #exame 19-20 especial
3.
consider a seguinte instrução:
java.rmi.Naming.unbind(“rmi://reg.isec.pt/5001/time”);
java.rmi.Naming.bind(“rmi://reg.isec.pt/5001/time”, timeService);
java.rmi.Remote r = java.rmi.Naming.lookup(“rmi://reg.isec.pt:5001/time”);
a) explique o que identificam os elementos “reg.isec.pt”, “5001”, e “time”
b) deduza a sequência de acções/passos principais desencadedos quando esta insgtrução é invocada (ligações estabelecidas, mensagens trocadas, etc.) a resposta não deve incluir código
==teórica) #exame 19-20 especial
4. para uma aplicação desenvolvida em Java aceda a um determinado sistema de gestão de base de dados (SGBD), pode recorrer-se à API JBDC. para o efeito é necessário usar um driver adequado ao tipo de SGBD acedido (por exemplo, mysql-connector-java-5.1.45-bin.jar para MySQL e obdc8.jar para oracle)
explique:
a) o que é comum a todos os drivers JDBC, independentemente do SGBD alvo;
r:
todos oferecem a API jbdc, é o api do jbdc
b) o que difere entre drivers JDBC destinados a SGBD distintos
r:
são implementados de forma diferente
o protocolo de comunicação é diferente do procotolo de comunicação MySQL
==prática)
1. (pergunta de api rest) considere a seguinte mensagem HTTP destinada a pedir, a uma determinada API/serviço web, a lista de undiades curriculares concluidas por um determinado aluno, identificado através do seu número de estudante num determinado ano lectivo e assmindo um esquema de autenticação baseado em tokes:
POST /alunos/list/ucs/concluidas HTTP/1.1
Host: api.pd.com
User-Agent: curl/7.55.1
Student-number: 201012345
Year: 202-21
Accept: */*
{“Authorization”:”TK asdasdasdsadsadsad”}
Este pedido apresenta várias incorreções relativamente à aplicação dos principios REST e à estruturação habitual de pedidos HTTP (i.e, colocação da informação no formato adequado e na parte certa da mensagem).
a) complete o pedido HTTP seguinte de modo a que este seja uma reformulação correcta da mensagem anterior
R:
as boas práticas dizem que:
na URI deveia ser um GET
GET /alunos/list/ucs/concluidas HTTP/1.1
o token deve estar no cabeçalho e num campo chamado Authorization
e o numero do aluno devia estar no corpo do pedido ou colocar mesmo na URI, mas neste caso até podiamos fazer uso do token
e também existe um erro em /alunos/list/ucs/concluidas pois o list devia surgir no final. partir de uma coisa mais genérica e vamos afunilando
ou resposta possivel (com parametros):
GET /alunos/22232323/ucs/concluidas?year=2020-21 HTTP/1.1
Host: api.pd.com
User-Agent: curl/7.55.1
Student-number: 201012345
Accept: */*
Authorization:TK asdasdasdsadsadsad
ou
GET /alunos/22232323/ucs/concluidas?year=2020-21¬a-minima=15 HTTP/1.1
b) complete a mensaem HTTP seguinte, sendo este um exemplo de resposta ao pedido anterior e considerando que é devolvida uma lista com duas unidades curriculares, sendo cada uma caracterizada por apenas dois atributos: cod_uc e nota. Pode atribuir qualquer valor aos atributos desde que façam algum sentido no contexto da pergunta
HTTP/1.1 ??????
Content-type: application/json
Date: Tue, 2 Fev 2021 10:13:05 GMT
?????
r:
HTTP/1.1 200 OK
Content-type: application/json
Date: Tue, 2 Fev 2021 10:13:05 GMT
[{“cod_uc”:”1111″,”nota”:”11″},{“cod_uc”:”2222″,”nota”:”12″}]
cuidados:
ao invés de: Content-type: application/json
pode ser application/txt
ou pode ser application/html
==prática)
2. explique, sem recorrer a código, quais são as ações principais que o método stop realiza ao ser invocado no pedaço de código abaixo (nota: não é o objectivo do méotod, ou seja, parar um senor remoto com código igual a 2, que deve explicar)
import Java.rmi.*
Remote ref = Naming.Lookup(“rmi://193.138.11.34/sensors_controller”);
ControllerInterface remoteSenosrs = (ControllerInterface) ref;
remoteSenosrs.stop(2);
a resposta deve obrigatoriamente mencionar os termos “serviço RMI”, “TCP”, “porto de escuta automático”, “endereço de IP”, “serialização binária” ou algo relacionado, “pedido” e “resposta”, entre outros possiveis. Quando referir os termos “porto de escuta automático” e “endereço IP” e “endereço IP” deve igualmente indicar onde os respetivos valores estão guardados. seja analitico e apresente a resposta soba forma de uma sequência ordenada de acções/passos (10 no máximo)
r:
==prática)
1. Pretende-se que desenvolva, em linguagem Java, um método atendendo aos seguintes requisitos:
Protótipo do método pretendido:
void processRequest(Socket s) throws Exception;
O socket TCP s já se encontra criado e conectado a um par remoto, estando pronto para o envio e recepção de dados;
O médoto processRequest vai recebendo objectos serializados do tipo Request através do socket s até que ocorra uma excepção qualquer;
A classe Request possui, entre outros, os métodos int getUdpPort(), String getIpAddress() e String getMsg();
Para cada objecto Request recebido, a string devolvida pelo método getMsg() é enviada, através do protocolo UDP (DatagramSocket) e em formato texto (i.e., sequência de caracteres) para o destino com o endereço IP e o porto estipulados;
Quando ocorre uma excepção de qualquer tipo, o método processRequest:
Encerra o socket s;
Apresenta a mensagem associada à excepção;
Volta a lançar a excepção, o que faz com que termine.
import java.net.*;
void processRequest(Socket s) throws Exception
{
. . .
while(true)
{
/* Receive a serialized Request object */
. . .
/* Transmit the specified message to the specified IP
address and UDP port.
The message is transmitted as a sequence of characters (i.e., it is not transmitted as a serialized String object).
*/
. . .
}
}
r1:
para:
O médoto processRequest vai recebendo objectos serializados do tipo Request através do socket s até que ocorra uma excepção qualquer;
temos:
criar um objecto inpuToStream
e vamos fazendo read object com cast para Request
para:
Para cada objecto Request recebido, a string devolvida pelo método getMsg() é enviada, através do protocolo UDP (DatagramSocket) e em formato texto (i.e., sequência de caracteres) para o destino com o endereço IP e o porto estipulados;
temos:
pega no Request e no getMsg() e getBytes()
e de seguida construir um dataGramPacket com o inetadress passado o byname o getIpAddress() e getUdpPort() criar o DatagramSocket e enviar
e apanhar as excepções
r2 final:
import java.net.*;
class Exame{
void processRequest(Socket s) throws Exception
{
if(s==null){
//return;
throw new NullPointerException(“socket s passado como null”);
}
DatagramSocket ds =null;//crio e vi sempre usado o mesmo socket
//e foi passado para fora do try para poder criar a excepção
try{
ObjectInputStream oin = new ObjectInputStream(s.getInutStream()); //aqui porque só se abre um ficheiro uma vez e já ta
ds = new DatagramSocket();
//para usar o DatagramPacket
while(true)
{
/* Receive a serialized Request object */
//
Request req = (Request)oin.readObject();
. . .
/* Transmit the specified message to the specified IP
address and UDP port.
The message is transmitted as a sequence of characters (i.e., it is not transmitted as a serialized String object).
*/
//se fosse necessário sair do ciclo
if(req.getMsg().equals(“EXIT”){
return;
}
DatagramPacket pkt = new DatagramPacket(req.getMsg().getBytes(), req.getMsg().getBytes().lenght, InetAddress.getByName(req.getIpAddress()), req.GetUdpPort() );
//ObjectInputStream oin = new ObjectInputStream(s.getInutStream());//sai daqui
//agora o datagramSocket para enviar a mensagem
//DatagramSocket ds = new DatagramSocket(); //sai daqui
//enviar a mensagem
ds.send(pkt);
}
} catch(Exception e){
System.out.println(“Excepcao :”+ e );
//e para lançar a excepção é preciso ainda fazer:
throw e;
}
finally{
try{
s.close(); //este try abafa a IOException que for gerada, apenas aqui
}catch(IOException e){}
if(ds!=null){ds.close();}
}
}
}
//tudo que é feito no finally é feito ao inves de usar
catch(Exception e){
s.close();
}
r3:
e se no socket podermos receber objectos do tipo Request ou do tipo XPTO
import java.net.*;
class Exame{
void processRequest(Socket s) throws Exception
{
. . .
while(true)
{
/* Receive a serialized Request object */
ObjectInputStream oin = new ObjectInputStream(s.getInutStream());
Object obj = oin.readObject();
if(obj instanceof Request){
((Request).oin).getUdpPort();
}else if(obj instanceof XPTO){
((XPTO).oin).getUdpPort();
}
. . .
/* Transmit the specified message to the specified IP
address and UDP port.
The message is transmitted as a sequence of characters (i.e., it is not transmitted as a serialized String object).
*/
. . .
}
}
}
==prática)
3. (RMi) Pretende-se que desenvolva um serviço remoto Java RMI, com um mecanismo de callback, atendendo aos seguintes requisitos:
Nome da classe que representa o serviço: MessageReflector;
Interface remota implementada pelo serviço MessageReflector:
Nome: MRInterface;
Métodos:
boolean registerClient (MRClientInterface cliRef);
Se ainda não existir, acrescenta a referência RMI passada como argumento a uma lista interna e devolve true. Se já existir, ignora o pedido e devolve false.
Notas:
1. Em vez de uma lista, também pode recorrer a um conjunto;
2. Cada cliente implementa um serviço RMI baseado na interface remota MRClientInterface.
boolean unregisterClient (MRClientInterface cliRef);
Se existir, remove a referência RMI passada como argumento da lista interna e devolve true. Caso contrário, devolve false.
void broadcastMessage(String msg);
Comunica a string passada como argumento a todos os clientes registados. Para o efeito, invoca o método void postMessage(String msg) pertencente à interface remota MRClientInterface. Qualquer problema que surja na invocação do método postMessage leva à eliminação da respectiva referência remota (i.e., do cliente) da lista interna.
int getNumRegisteredClients();
Devolve o número de clientes registados (i.e., o número de referências remotas existentes na lista interna).
r:
Class MessageReflector extends unitCastRemoteObject implments MRInterface {
//fazer o construtor vazio
MessageReflector{}
//e os métodos
boolean registerClient(){}
//enivar a todos
com broadcastMessage e ir ao arrayList e chamar
}
r2 final:
notas:
os clientes devem registar.se, isto é , invocar um método do serviço
não é preciso o main do servidor
//a base sem RMi
interface MRClientInterface extends Remote{
void postMessage(String msg) throws RemoteException;
}
public interface MTinterface{
//métodos
boolean registerClient (MRClientInterface cliRef);
boolean unregisterClient (MRClientInterface cliRef);
void broadcastMessage(String msg);
int getNumRegisteredClients();
}
//classe que implementa a interface
class MessageReflector implements MRInterface
{
//lista de referencias remotas para os clientes
List clientList = new ArrayList<>();
@Override
public boolean registerClient (MRClientInterface cliRef){
return false;
}
@Override
boolean unregisterClient (MRClientInterface cliRef){
return false;
}
@Override
void broadcastMessage(String msg){
}
@Override
int getNumRegisteredClients(){
return -1;
}
}
//agora aplicar o RMi
interface MRClientInterface extends Remote{
void postMessage(String msg) throws RemoteException;
}
public interface MTinterface extends Remote{
//métodos
boolean registerClient (MRClientInterface cliRef) throws java.rmi.RemoteException;
boolean unregisterClient (MRClientInterface cliRef)throws RemoteException;
void broadcastMessage(String msg) throws RemoteException;;
int getNumRegisteredClients() throws RemoteException;;
}
//classe que implementa a interface, e agora já é um serviço e surge extends UnicastRemoteObject
//servidor concorrente UnicastRemoteObject
//e cada cliente que se ligue vai ser criada uma thread
class MessageReflector extends UnicastRemoteObject implements MRInterface
{
//lista de referencias remotas para os clientes
List clientList = new ArrayList<>(); //este atributo é mexido por várias threads, vou então serializar
//e falta o construtor
public MessageReflector () throws RemoteException{}
//ou public MessageReflector (Listl) throws RemoteException{}
//e em todos os métodos da interface remota surge throws RemoteException
@Override
public synhcronized boolean registerClient (MRClientInterface cliRef) throws RemoteException{
//se já existe, do tipo equals
if(clientList.contains(cliRef)){
return false;
}
return clientList.add(cliRef);
}
@Override
boolean synhcronized unregisterClient (MRClientInterface cliRef) throws RemoteException{
return clientList.remove(cliRef);
}
@Override
void synhcronized broadcastMessage(String msg) throws RemoteException{
//versão1
for(MRClientInterface cli: clientList){
try{
cli.postMessage(msg);
}catch(RemoteException e){
clientList.remove(cli);
}
}
//versão2 com indices
for(int i = 0 ; i<clientList.size();i++){
try{
clientList.get(i).postMessage(msg);
}catch(RemoteException e){
clientList.remove(i–);
//i–;
}
}
}
@Override
int synhcronized getNumRegisteredClients()throws RemoteException{
return clientList.size();
}
}
//ou synhcronized por bloco
@Override
public boolean registerClient (MRClientInterface cliRef) throws RemoteException{
synhcronized{
}
return false;
}
Parte 1 de 37, apontamentos
#sockets Java
na comunicação na internet entre aplicações existem dois protocolos: o UDP e o TCP
o ip identifica a máquina, e o porto ajuda a app a saber que a comunicação é para essa app
UDP – enviamos mensagens (datagramas) e que inclui:
dados da mensagem (conteúdo) e um envelope com ip, porto de destino e IP porto de origem
UDP não faz verificação, são enviadas cartas (como se fosse um envelope)
TCP – temos um fluxo de BYTES, diferente de UDP
existem classes em java importantes para proceder à comunicação:
inetadress, manipula relações com endereços e resolução de nomes
datagram packt, tem atributos e métodos e que vai ser encapsulada num datagramPackt
datagram socket, só o UDP tem isto porque se trabalha com datagrams
o Inetadress:
encapsula endereços IP
não tem construtor
tem métodos estáticos
getByName(IP ou nome)
métodos a aplicar depois:
getHostAddress
getHostName
getAllByName(array)
para saber qual o meu ip:
inetAdress localAdress = InetAddress.getLocalHost();
e uma exceção:
catch(UnknowHostException e){
…
}
DataGramPacket
encapsula as mensagens individuais
construção de um datagram UDP para envio
Uma mensagem tem um endereço ip, um porto e uma mensagem (conteúdo)
DataGRamPAcket packet = new DataGramPAcket(data, data.length, addr, 2000);
data vem byte [] data = new byte[128]
data.length vem 128
addr vem InetAdress addr = InetAdress.getByName(“192.168.0.1”);
2000 vem o porto
Operação de receção de um DATGRAM PACKET
assim no recetor uso outro construtor
try{
DATAGRAMPACKET packet = new DTAGRAMPACKETS (new byte[256], 206);
DATAGRAMSOKCET socekt = new DATAGRAMSOCKET(2000);
boolean finished = false;
while(!finished){
socket.receive(packet);
…
}
socket.close();
}catch
#protocolo UDP
a class DATAGRAMPACKET tem vários métodos:
send
receive (bloqueante)
close
setTimeout(0), desbloqueio o TIMEOUT é um no TIMEOUT
o lenght, consoante o contexto de utilização um determinado packet pode significar:
quantidade para enviar
quantidade para receber/aceitação
quantidade que foi recebida
#exemplo como enviar uma mensagem:
DATAGRAmSOCKET socket = new DATAGRAMSOCKET();
DATAGRAMPACKET packet = new DATAGRAMPACKET( new byte[256], 256);
packet.setAddress(INETADDRESS,getByName(someHost));
packet.setPort(2000);
boolean finished = false;
while(!finished){
//-> escrever no buffer do packet
seocket.send(packet);
//-> verificar se existe mais coisas para enviar
}
socket.close();
#protocolo TCP
relembrar que no UDP:
DATGRAM PACKT, que encapsula uma mensagem com endereços (endereço, porto, dados recebidos)
DATAGRAM SOCKET, end point de uma comunicação, onde enviamos e recebemos bytes
ÎNETADRESS, serve para encapsular o endereço ip e os nomes do dns
Protocolo TCP:
não é orientado a mensagens;
serve para comunicação ponto a ponto (entre dois extremos)
abstração do socket (ligação virtual)
o socket está ligado a um endereço remoto (end point), surge o conceito de fluxo de dados
o que vai ser colocado no buffer são bytes e não mensagens (é o mesmo que escrever num ficheiro)
enviar bytes para uma aplicação remote, como se estivesse a escrever num ficheiro
UDP não faz controlo de fluxo, não verifica o numero de sequência, não deteta se existem mensagens perdidas, não pede retransmissão (envio uma carta e esqueço a carta)
TCP, as instâncias de TCP, trocam informações, mensagens de controlo, confirmações, timeouts, para garantir que os bytes são colocados no socket de destino pela mesma ordem e sem haver perda de bytes no meio
#entrada/saída
input stream e output stream, são classes abstratas cujos métodos não estão implementados
vão-se é obter subclasses que vão implementar métodos.
INPUTSTREAM (vou ter um read) e OUTPUTSTREAM (vou ter um write) geram exceções IOException
usar SCOKET ou ArrayBytes ou Ficheiro, vai ser indiferente
pseudocódigo:
a conexão (servidor, recebe a ligação)
xxServerSocket // Socket socket = new Scoket (“www…”, 80);
a transferência
xx Socket
outros exemplos:
socket (host, port );
socket (host, port, bindAddress, localhost)
onde bindAddress, especifica-se a placa (por exemplo um das duas placas do portátil, rede sem fios)
onde localhost, porto do cliente
por exemplo: socket(…, …, InetAddress.getByNumber(“10.10.10.10”), 5001);
a entrada e saída de dados tem que ser feita através desta placa de rede, mas pode acontecer que não queremos restringir placas mas fixar porta 5001, então surge
socket(…, …, InetAddress.getByNumber(“0.0.0.0”), 5001);
exemplo no cliente:
try{
Socket mySocket= new Socket(“www.sol.pt”, 80);
….
}catch(Exception e){
System.err.println(“Err – ” + e);
}
O socket TCP, tem métodos:
getOutPutStream()
getInputStream()
getLocalPort
getPort, acesso ao porto remoto
GetTimeout()
por exemplo no cliente:
try{
Socket socket = new Socket(someHost, somePort);
BufferReader reader = new BufferReader(new InputStreamReader(socket.getInputStream()));
PrintStream pstream = new PrintStream(socket,getOutPutStream());
}catch(IOException e){
System.err.println(“erro – ” + e);
}
em que: socket.getInputStream(), faço o read
em que: socket,getOutPutStream(), faço write bytes
por exemplo, operação de leitura e que não fique bloqueado para sempre:
try{
Socket socket = new Socket(someHost, somePort);
socket.setTIMEOUT(2000); // onde setTIMEOUT(0);//desliga-se o TIMEOUT
BufferReader reader = new BufferReader(new InputStreamReader(socket.getInputStream()));
PrintStream pstream = new PrintStream(socket,getOutPutStream());
}catch(Interrupt IOException e){
timeoutflag = true;
}catch(IOException e){
System.err.println(“erro – ” + e);
System.exit(0);
}
#protocolo TCP
serverSocket(porta) e tem alguns métodos como é o caso do close()
o serverSocket não serve para enviar dados e receber, este só serve para aceitar ligações
#aplicações multicast
endereços de classe D (11110)
representam grupos (ou endereços)
como enviar para um grupo e como receber?
escrever via broadcast (255.255.255.255 6001)
assim todas as aplicações que estão a correr na mesma máquina no domínio de difusão e que tenham um socket associado ao porto 6001 vão receber a mensagem
exemplo:
InetAddress group = InetAddress getByName(“224.1.2.3”);
MulticastSocket socket = new MulticastSocket(port); //port é o porto de escuta
socket.joinGroup(group); //joinGroup(group) para apanhar o que aparece na rede destinada ao 22.4.1.2.3 port
socket.setTimeToLeave(1); // setTimeToLeave, tempo de vida da mensagem, neste caso (1) elimina, e fica a zero e não reencaminha
e para enviar e receber:
DATAGRAM packet = new DATAGRAM (buffer, buffer.lenght, group, port);
socket.send(packect);
//como pertenço ao mesmo grupo, também recebo
byte[] response = new byte[1024];
DATAGRAM packet = new DATAGRAMPACKET(response, response.length);
socket.receive(packet);
Exemplo:
String NICID = “127.0.0.1”,”en0″,…
NETWORKINTERFACE nif;
try{
nif = NETWORKInterface.getByInetAddress.getByName(NICID));
}catch(Exception ex){
nif = NETWORKInterface.getByName(NICID);
}
socket = new MultiCast(port);
socket.joingroup(new InetSocketAddress(group, port), nif);
em que:
joingroup, associo a um grupo
InetSocketAddress, completo IP+porto
nif, qual a interface de rede a associar ao grupo
#serialização de objectos
Esta é a forma mais simples de trocar informação
A informação está encapsulada em objectos
Serialização vs DesSerialização
a Serialização é binária, mas exibe em formato de texto como o JSON
#serialização de objectos, ligações TCP
exemplo:
s = new Socket(serverAddress, serverPort); // estabelecer a ligação
in = new ObjectInputStream(s.getInputStream());
out = new ObjectOutPutStream(s.getOutPutStream()); //enviar
out.writeObject(object to transmit); //escrever no object
//ou out.writeUnShared(object to transmit); //deve ser usado, por exemplo para enviar um arraylist então o usado é o unshared para evitar caching
out.flush();
ou usar writeobject mas fazer antes o out.reset() e ficaria:
out.reset();
out.writeObject(object to trnsmit);
//e do outro lado faz-se a leitura
returnObject = (MyClass)in.readObject();
#serialização de objectos ligações UDP
o UDP não tem fluxo de bytes, datagrams)
exemplo para o envio:
s = new DatagramSocket();
bout = new ByteArrayOutputStream();
out = new ObjectOutputStream(bout);
out.writeObject(Object to transmite);
//ou
out.writeUnshared(object to transmite);
out.flush();
packet = new DatagramPacket(bout.toBytetoarray(), bout.size(), serverAdress, serverPort);
s.send(packet);
exemplo para receber:
packet = new DATAGRAM(new Byte[MAX_SIZE], MAX:SIZE);
s.receive(packet);
n = new ObjectInputStream(new ByteArrayInutStream, packet.getData), 0, packet.getLenght());
returnObject = (MyCalss) in.readObject();
#threads
processo é diferente de thread
todas as threads pertencem ao mesmo processo, as threads são linhas de execução
as threads podem ser iniciadas em dois modos distintos:
modo por omissão, modo normal (modo utilizador) // bloqueante
modo através do daemon(serviço para correr em background) // não bloqueante
Uma aplicação em java termina quando já não existe qualquer, em que já não existem threads em modo utilizador activas.
As thraeds activas em modo de utilizador, mesmo chegando ao fim do main elas continuam activas, se forem as threads em modo daemon, chegada ao fim do main elas terminam
public class RunnableThreadDemo implements java.long.Runnable
{
public void run(){
SystemOut.println(“….”);
}
public static void main (String args[]){
System.Out.println(“…”);
Runnable run = new RunnableThreadDemo();
System.Out.println(“…”);
thread t1 = new Thread(run, “thread 1”); //run, é o nome da thread
System.Out.println(“…”);
thread t2 = new Thread (run, “trhead 2”); //run é o nome da thread
System.Out.println(“…”);
t1.start();
t2.start();
}
}
a diferença entre os dois modo de criar threads pode ser importante
assim o método II é melhor que o método I, já que posso criar várias threads baseadas no mesmo objecto runabble e elas vão partilhar os mesmos membros. posso assim ter várias threads concorrentes mas a trabalhar sobre os mesmos dados.
E outra vantagem é contornar uma das limitações do já de não haver herança múltipla
class ExtendThreadDemo extends java.long.thread // esta classe não pode estender outro tipo de objecto
assim consigo dar a volta a isso fazendo/usando:
class ExtendThreadDemo implements java.long.thread
eu posso implementar vários tipos de classes mas só posso derivar de uma classe
threads, faz-se o new thread mas depois tem que se fazer o start, e só depois do start o new cria um objecto que representa uma thread, mas o start lança de forma efectiva
#interromper threads
é desaconselhável
thread sleep- > interreupt -> resume
alternativa é a thread que a lançar, fechar a socket, ao fechar é gerada uma exceção na thread e antes de fechar o socket eu coloco um atributo na thread para ela saber que é para terminar
#parar threads usar o stop
fazer uso de uma boolean e “avisar” que vai ter que encerrar
#operações sobre threads
verificar se ainda está viva:
if(t1.isAlive(){ //booleand
…
}
e nunca usar um while..
#método join
bloqueia, e só regressa depois da thread estar inactiva
t1.join(1000,10000);
em que 1000, é o numero máximo de segundos milésimo de segundos
100000, são nanosegundos
exemplo:
thread die = new WaitForDeath(); //a thread
die.start(); //inica a thread
die.join(); // bloqueia ate a thread terminar
#sincronização de threads
concorrência no acesso a recursos partilhados
solução: serializar o acesso ao recurso partilhado, isto é, enquanto uma thread está a mexer nos recursos, as outras threads que pretendam aceder aos recursos ficam bloqueadas, ou seja, surge então o objecto sincronização
acesso mutuamente exclusivo
assim se surgir outra thread que quer aceder a métodos não podem executar esse ou outro métodos do objecto
a sincronização pode se feita:
método // bloqueia apenas alguns dos métodos
bloco de código
#sincronização ao nível do método// thread safe
public synchronized void mudaData() {…}
public synchronized void changeData() {…}
exemplo:
public class someClass{
public synchonized void ChangeData(){…}
}
O = new someClass();
t1 e t2 têm a referêcnia para O
t1 chama o método changeData
e se t1 chamar o méotodo changeData, fica bloqueada
#sincronização ao nivel do bloco de código
sincronização referente a um bloco
não é necessário os métodos serem synchronized
existe o thread-safe (serializado) sem necessidade de ter acesso ou alterar o código fonte
synchronized (Object O){
…
}
esta forma dá mais flexibilidade
se for só um classe minha será mais fácil colocar o método sincronized mas se for uma que já existe será o modo bloco
#grupos de threads
é limitado, um conjunto de operações limitado
#comunicação entre threads
no mesmo processo, no mesmo espaço de endereçamento é feito através de pipes de comunicação:
_troca directa de dados entre threads
_comunicação bidirecional
(temos usado um BufferedReader bin = …
#notificação entre threads
surgem os métodos:
Object.wait();
Object.notify();
Object.notifyAll();
#prioridades das threads
abordagem round-robin
prioridades variam entre:
1 mais baixa
10 mais alta
com uso de:
MAX_PRIORITY
NORM_PRIORITY
MIN_PRIORITY
métodos:
t.setPriority(thread.MIN_…)
#servidores TCP concorrentes
while(true){
cliente = socket.accepts();
t = new thread();
t.start();
…
}
#computação paralela baseada em múltiplas threads
processamento real
#exercicio
resolver um proxy: é uma aplicação que serve de intermediário entre duas aplicações em rede
usando TCP: (guarda log dos acessos)
o proxy para fazer logs do que é trocado
um proxy para servidor é uma ponte. o servidor do mail do isec pop-isec.pt:110
um server socket no porto 8080, e crio uma thread que vai tratar o que se pasa no socket, mas essa thread tem outra socket para comunicar com o servidor de mail do isec (cliente-servidor)
para cada cliente exist uma thread cirada
essa thread tem um socket para comunicar com o cliente
essa thread tem um socket para comunicar com o pop.isec (servidor)
mais ainda não se consegue receber um char e reencaminhar porque existe um sistema de bloqueio de espera de mensagem no socket
usar um timeout não se pode fazer porque é espera activa, assim para cada cliente vai ser necessário duas threads, e as duas threads têm acesso aos mesmos sockects
uma thread tem acesso a ler bloqueada num socket e aquela que recebe envia para outro socket e outra faz o inverso
#arquitectura n-tier
separação lógica e física
a arquitetura 3-tier é mais habitual:
apresentação
lógica (do negócio)
dados (MySQL)
o 3-tier, é parecido com o MVC:
camada de apresentação -> cliente
camada lógica -> SGRDS e servidores
camada de dados -> usar o MySQL
#JDBC
java database connectivity
Connection con = DriverManager.getConnection(BD, username, password);
statment stmt = con.createStatment();
resultset rs = stmt.executeQuery(“select * from table;”);
while(rs.next){
int x = rs.getInt(“a”);
String s = rs.getString(“b”);
float x = rs.getFloat(“c”);
}
porque é que temos que usar drivers diferentes para bases de dados diferentes? se tiver que usar SQL, porque é que tenho que usar um driver diferente se tiver que usar ORACLE?
porque o protocolo de comunicação é diferente
#inovação remota de métodos
o middleware, sistema que vai abstrair o programador dos aspectos de baixo nivel, nomeadamente de:
troca de mensagens/comunicação
protocolo de comunicação
sistemas operativos
hardware
exemplos de middleware:
RMi
RPC
CORBA
NetRemoting
um proxy que tem os métodos, e eu localmente tenho um objecto que tem os mesmos métodos
RPC é o inicio da história para o paradigma dos sistemas distribuídos (miiddleware)
os passo do RPC
passo1: o servidor fica a correr e vai-se registar na porta 111
passo2: o cliente solicita o porto do servidor
passo3: recebe a porta
passo4: faz o pedido
passo5: recebe a resposta
#introdução ao java RMi
agora ao invés de se chamar funções, vou chamar métodos usando objetos remotos
o input ao sistema é uma interface (conjunto de protótipos de métodos)
#arquitectura java RMi
existem servidores, clientes, RMI registry
os passos do RMi:
1_ o servidor regista no Rmi registry
2_ o RMiregistry providencia referências ao cliente
o que é que um serviço e um proxy têm em comum?
a interface, os métodos que implementam
o Sturb (ou proxy) é do lado do cliente e actua como um proxy. Implementa neste a interface remota, é invocado pelo cliente, envia mensagem ao serviço.
o Skeleton é do lado do servdor, aguarda pedidos na aplicação servidora, invoca o método pretendido, devolve o resultado ao Sturb.
A comunicação é feita via serialização e por isso todos os argumentos que se passam em funções e resultados têm que ser serializados
porque razão é que o java RMi nas interfaces remotas tem que ter os argumentos e os resultados serializados?
porque o sistema, invocamos o método remoto e o que acontece é que é enviado um objecto que representa um pedido para o servidor, e o RMi faz a serialização dos objetos logo o pedido vai ter a identificação do método, etc, e assim tem que ser tudo serializado
#Arquitectura RMi
permite chamar os métodos de um serviço que não está na minha máquina, sendo que existem três componentes principais e que são: servidor RMi, cliente RMi, RMi registry
o servidor RMi: usa TCP, com um server socket à escuta num porto, é concorrente (sempre que existe um pedido de ligação cria uma thread, essa thread recebe pedidos, vê qual o objecto e qual o método para executar, e executa e devolve o resultado na origem.) No servidor só temos que especificar o que o método faz
o cliente RMi: aplicação que tem referências para objectos remotos. O cliente quando contacta o RMi registry recebe o Sturb. E no Sturb tem dois membros obrigatórios: o ip da maquina e o porto de escuta
o RMi registry: é o serviço que está à escuta num porto automático TCP, sendo que os clientes contactam o RMi Registry TCP
#Passos principais
1) definir a interface remota: métodos, com argumentos e valor de retorno (Sendo que tudo o que é valor de retorno tem que ser serializavel)
2) implementar o serviço: ter classes que implementam a interface
3) é preciso um servidor (uma aplicação que cria objecto, vai registar no RMi registry)
4) os clientes (é uma aplicação que tem que invocar o método no serviço XPTO, assim em vez desta aplicação fazer um NEW, vai obter uma referência remota, contact o servidor, e se o serviço existir eu obtenho o sturb/proxy (referencia remota))
5) lançar o RMi registry (1099, TCP)
6) lançar o servidor
7) correr os clientes
#interfaces remotas
por exemplo controlar uma lâmpada remotamente
surge então uma aplicação em java, em que no main faz-se um NEW controlador (que poderia ter alguns parametros) e nesta app apenas surge a opção do menu de ligar e desligar.
ainda no main do servidor, teria que criar um server socket que vai fazer accepts, se quiser qe seja concorrente lanço threads
então e na comunicação posso usar mensagens curtas, booleans, ou objectos serializados com mais campos
do lado do cliente existe um socket que constroi os pedidos
usando o RMi vamos abstrairnos desta situação, com o RMi vai ser mais simples pois não se pensa em mensagens, mas sim nos servidores, e quais os métodos que temos nos servidores e as apps clientes vão invocar métodos do utilizador (gets, sets, ..) (por baixo existe o TCP, serialização, mas não somos nós a tratar disso)
No RMi temos que obrigatóriamente usar em todos os métodos o throws java.rmi.remoteException
public void on() throws java.rmi.remote.exception
e as interfaces remotas têm que ser:
public interface Classe extends java.rmi.remote {
public void ont() throws java.rmi.remote.exception
muito importante:
throws java.rmi.remote.exception
e
public interface Classe extends java.rmi.remote
assim:
1) no servidor existem métodos
2) os clientes vão invocar os métodos no utilizador (gets, sets…)
no servidor java RMi, vai pensar no que quero que seja invocado remotamente
no servidor, exemplo:
public interface RMiLight extends java.rmi.remote{
public void on() throws java.rmi.remoteException;
public void off() throws java.rmi.remoteException;
public void isOn() throws java.rmi.remoteException;
}
os métodos podem lançar para fora excepções que eu entender, em que, e é muito importante:
todos os métodos têm que lançar a expeção java.rmi.exception
as interfaces remotas extends java.rmi.remote
implementar o serviço, exemplo:
public class RMiLight extends java.rmi.unicastRemoteObject implements RMiLight{
public RMiLight()throws java.rmi.remote.exception{
…
}
public void on()throws java.rmi.remoteException {
…
}
}
em que:
public class RMiLight extends java.rmi.unicastRemoteObject implements RMiLight é um servidor base que não executa nada TCP
public RMiLight()throws java.rmi.remote.exception é um construtor obrigatorio. os construtores não aparecem na interface remota, mas os serviços remoto precisam de construtor que lançam excepções remotas (nem que seja vazio)
nos serviços tenho:
os métodos que pretendo que sejam invocados remotamente
só os métodos que fazem parte da interface remota é que precisam do RemoteException?
assim os outros métodos do serviço que não fazem parte da interface remota já não vão dar
assim ao criar uma instância da classe RMiLightBullImp no servidor vem que, exemplo do servidor:
public class void main(){
try{
//lançar uma thread em ciclo que cria +1 thread para cada cliente em paralelo que espera pedido de ligação
RMi bs = new RMiLightImp();
RemoteRef location = bs.getRef(); //não é necessário
string registry = “localhost”; //ip do registry e nó do serviço
if(args.lenght >1) { registry = args[0]; }
string registration = “rmi//” + registry + “/RMiLightBulb”; //registo do serviço
naming.rebind(registration, bs); //RMi e serviço
}catch(Remote Exception e){
}
}
apesar de chegar ao fim do main, ainda existe uma thread no modo de utilizador, e as aplicações em java só terminam se não existir mais threads de modo utilizador a decorrer
as aplicações agora só precisam de saber qual o IP onde está e qual o porto do servidor
naming.rebind(registration, bs);
em que:
se estabelece uma ligação TCP
no porto 1099 (porto de escuta do RMi registry)
manda-lhe uma margem para registar como o nome RMi Light bulb a referencia ao objecto Bs
rmi://192.10.10.10/xpb
o que faz quando se faz naming rebind
isto não estabelece uma ligação com um serviço
naming.lookup(rmi://192.10.10.10/xpb);
o naming.lookup no cliente para ele obter a referência para um serviço com este nome
quando se faz o lookup o que é feito é uma ligação TCP com qualquer coisa no IP no porto 1099 que é do registry e quero obter uma referência para um objecto com o nome xpb, esta referência tem interface e tem IP e porto
qual a diferença entre o método Bind e Rebind? (Bind e Rebind, tem a ver com tabelas no registry)
Com o rebind se existir é substituído senão existir cria
com o bind se não existir cria e se já existir cria uma excepção
no cliente o que é que faz o ON em bullbService.on(); sabendo que existiu
SErviceRmi bullBservice = (serviçoRmi) remoteSErvice
o cliente não faz um NEW local do objecto o que ele faz é um naming.lookup
no cliente depois vou ter um objecto que implementa a interface do serviço (on, off, …)
into é em sturb, e vai ser enviado ao fazer on, envia serializado a operação que tem que ser executada e que é o on, e o serviço recebe o pedido, executa e devolve o resutlado
qual é o aspecto comum entre proxy/sturb e o serviço?
é a interface, tem um conjunto de métodos coincidentes isto é, no serviço existe um on() e no sturb também existe um on() que na realidade envia uma mensagem para o outro lado para ligar
#cliente RMi
naming.lookup(registry);
isto faz uma ligação TCP com o RMi registry. faz um pedido do RMi registry e recebe um array de strings com o nome dos serviços registados
registry é o ip da maquina
relembrar que no RMi registry podemos solicitar:
lookup, pedir uma referÊncia para o objecto
bind/rebind, regista um serviço
#funcionalidades adicionais
para alunar uma referência que está na tabela
naming.unbind(“rmi://192.0.0.1/RMiLightBuld”)
para terminar no servidor e no main:
unexportObject(bulbSErvice, true);
em que bulbSErvice é o serviço
No servidor pode ser criado algo do tipo, prima qualquer tecla para terminar o serviço e com a inclusão do endpoint Object termina a thread em modo de utilizador
e só termina depois dos clientes serem atendidos, não é de forma abrupa, nas se for false termina logo tudo
o que significa?
endPoint(10.20,4,128.77:53561);
10.20,4,128.77 é o IP do serviço
53561 é o porto automático, criado pelos server socket
quando o cliente faz o lookup do registry obtêm uma referencia remota, o que se indica no lookup é o ip do registry e o porto (do registry) mas aqui é isto que eu obtenho
#funcionalidades adicionais
no servidor vou lançar o registry da maquina:
createRegistry
getRegistry
#invocação remota dos métodos
desenvolver aplicações remotas sem ter que se preocupar com sockets, sem usar o paradigma de troca de mensagens, sem usar TCP/UDP directamente
no cliente temos um Sturb (proxy), uma referência para o objecto remoto
no servidor existe o Skeleton, um servidor TPC, concorrente que recebe os pedisos, serializados, serialização binária do java.rmi, identifica qual o método que é para invocar, e argumentos, invoca e envia o resultado, e o método no cliente regressa e não é proxy
o que é que é comum entre o serviço (servidor) e a referência remota (Sturb, no cliente)?
é a interface implementada
o proxy não faz aquilo que é suposto o método fazerem, o que ele faz é pegar nos argumentos e envia para o servidor (Skeletton) que no servidor vai ser executado, que depois serializa e envia a resposta e o Sturb devolve a resposta ao cliente
quando o serviço é lançado (no servidor) ele regista-se no RMi registry (que é tipo um DNS) onde fica registado o IP e o porto onde pode ser encontrado o serviço
o cliente contacta o RMi registry à procura do serviço
o que acontece inernamente (por baixo) no cliente RMi quando ele faz so dos métodos, por exemplo em:
bulbSErvice.isOn()
é feito um pedido de envio
aguarda resposta
o pedido é serialziado
e é devolvida a resposta
situação de dois clientes acederem ao mesmo objecto ao mesmo tempo?
o cliente através do lookup contacta o registry (TCP, 1099) e envia o pedido para o que quer
o cliente depois recebe a referência remota do objecto, que tem a interface pretendida (métodos…) e também tem o ip e porto do serviço (serviço APi)
no servidor depois de contactado cria uma thread que vai cuidar desse cliente
e se existir outro cliente vai também ser o mesmo procedimento, e no serviço (servidor) é criada outra thread
assim eu tenho que verificar se é critico os acessos concorrentes, dois clientes têm acesso a um determinado serviço, estão a aceder ao mesmos erviço e mesmos recursos, então eu terei que colocar nas classes concretas/serviços o sincronized
por exemplo:
private boolean lightOn() sincronized;
pois pode ser alterada pelos vários clientes logo estes métodos têm que ser sincronized
#callBacks Rmi
callback são notoificações assincronas (o observador observável), por exemplo:
as vistas são actualizadas quando existem alterações no modelo, esta operação é o callback
quando existe um alteração no modle é notificada (avisada) a vista, por exemplo:
o cliente tem a referêcnai remota do serviço
o cliente quer saber sempre quando existe uma alteração em um membro do serviço
o cliente é um observador e o serviço um observavel
ambos estão na mesma maquina virtual
o servidor vai ter uma lista, coleção de referecnias para aplicações (observador/clientes) que esão interessados em ser notificados, é uma lista de sockets
do lado do cliente existe uma thread que está sempre à escuta, que recebe a mensagem e atualiza a vista
mas agora usamos objectos remotos, a lista no servidor vai ter coisas que implementam interfaces remotas nos clientes
os clientes passam a ter uma interface remota que vai ser usada pelo servidor
é muito importante perceber: os clientes implementam uma interface remota
o cliente vai logo terminar?
no main do cliente encontra-se:
tenho uma referencia
obtive a temperatura
crio o serviço (NEW…)
registo o sensor (temperature change…)
mas a aplicação do cliente não termina porque foi criado um objecto do tipo unicast object, que tem uma thread que está à escuta no server socket e que é um serviço
#protocolo HTPP em java
no HTTP temos um pedido (get) e uma resposta, através de uma ligação TCP
na resposta surge sempre um código de 3 digitos, e um cabeçalho e um corpo (opcional)
#URi
URi ou URL,
o URi, é um identificador
o URL, é um locator
ambos querem dizer a mesma coisa, servem para identificar recursos
o que é que isto identifica?
RMi://services.isec.pt/servicosacademicos
RMi registry, que é uma base de dados com uma tabela que tem nome e caminho remoto (dos sturbs)
em que servicosacademicos é nome do serviço
na tabela surgem referências remotas, do tipo javaRMi remote
com o método lookup, obtenho o valor correspondente aos servicosacademicos
com o método nbing, serve para apagar
com o método bing ou rebind, serve para acrescentar (bind) ou para substituir (rebind)
#campos cabeçalho
expansivel – campos prédifinidos
pedido – usando o método get, recurso, protocolo, mudança de linha
get / widget / xpto / 3 / http/1.1 \n\n
repsosta – http/1.1 200 ok
em que 200 é o código
se for feito um post serve para actualziar recursos nos ervidor, ou submeter autenticação
#java.net.url
o que faz o openStramÎnputStream in = myURL.openStream();
faz uma ligação TCP no porto adequado no URL, envia para lá um get com o ficheiro não identificado por omissão
#URL connection
prmite aceder aos códigos de estado das mensagens de resposta
#alguns métodos de autenticação HTTP
fazer um pedido HTTP, reebo uma resposta por parte do servidor
básico: em cada pedido tenho o login e password que vai no cabeçalho, e no cabeçalho vem
Authorization: basic usernamepassword
codificado em base 64, e é apenas uma forma de codificar
#token
o token depois de ser feita a autenticação é dado ao utilziador um token que só lhe pertence e esse token é unico, só do individuo
este é o token que permite ao utilziador fazer as suas operações depois do login
//—– perguntas de exame:
==1)
aparece este bocado de código:
PrintStream pout = new PrintStream(out);
pout.printl(new Java.util.date());
pout.flush();
1) o que faz este código?
o new java.util.date() é escrito no pout
2) concorda com a seguinte afirmação:
“este pedaço de código escreve no ecrã a hora atual seguida de uma mudança de linha”
Não, não é totalmente coreto, pode ser mas também pode não ser, porque o printStream está a receber um objeto do tipo outputStream e o outputstream não é só System.out, não é só fileOutPutStream, ele pode estar a escrever isto para um ficheiro, ou para o ecrã pode ser para um socket TCP, como ode ser um byteArray outpuStream (temos aqui uma questão de polimorfismo)
==2)
multicast(subclasse de DATAGRAMSOCKET)
em que:
multicast: quando queremos também receber as mensagens que são enviadas para o grupo
DATAGRAMSOCKET: se eu só pretendo enviar para um grupo de multicast é o envio de um DATAGRAMSOCKET UDP clássico, enviar para um determinado IP/porto
não existe nenhum servidor de gestão de grupos
==3)
as threads podem ser iniciadas em dois modos distintos:
modo por omissão, modo normal (modo utilizador) // bloqueante
modo através do daemon(serviço para correr em background) // não bloqueante
Uma aplicação em java termina quando já não existe qualquer, em que já não existem threads em modo utilizador activas.
As thraeds activas em modo de utilizador, mesmo chegando ao fim do main elas continuam activas, se forem as threads em modo daemon, chegada ao fim do main elas terminam
public class RunnableThreadDemo implements java.long.Runnable
{
public void run(){
SystemOut.println(“….”);
}
public static void main (String args[]){
System.Out.println(“…”);
Runnable run = new RunnableThreadDemo();
System.Out.println(“…”);
thread t1 = new Thread(run, “thread 1”); //run, é o nome da thread
System.Out.println(“…”);
thread t2 = new Thread (run, “trhead 2”); //run é o nome da thread
System.Out.println(“…”);
t1.start();
t2.start();
}
}
a diferença entre os dois modo de criar threads pode ser importante
assim o método II é melhor que o método I, já que posso criar várias threads baseadas no mesmo objecto runabble e elas vão partilhar os mesmos membros. posso assim ter várias threads concorrentes mas a trabalhar sobre os mesmos dados.
E outra vantagem é contornar uma das limitações do já de não haver herança múltipla
class ExtendThreadDemo extends java.long.thread // esta classe não pode estender outro tipo de objecto
==4)
threads, faz-se o new thread mas depois tem que se fazer o start,e só depois do start o new cria um objecto que respresenta uma thread, mas o start lança de forma efectiva
==5)
complete o código, em que temos:
for(i = 0; i< nThreads; i++){
threads[i] = new ParallelPi(i+1, nThreads, nIntervals);
threads[i].start();
}
se eu estou a criar a minha thread com new ParallelPi, quer dizer que ParallelPi extends thread, se fosse implements runnable eu teria que ter um new Thread e em argumento um new ParallelPi
se existe um new ParallelPi e depois faço um start então é porque é extends thread e não implements Runnable
==6)
porque é que temos que usar drivers diferentes para bases de dados diferentes? se tiver que usar SQL, porque é que tenho que usar um driver diferente se tiver que usar ORACLE?
porque o protocolo de comunicação é diferente
==7)
um proxy que tem os métodos, e eu localmente tenho um objecto que tem os mesmos métodos
RPC é o inicio da história para o paradigma dos sistemas distribuídos (miiddleware)
os passo do RPC
passo1: o servidor fica a correr e vai-se registar na porta 111
passo2: o cliente solicita o porto do servidor
passo3: recebe a porta
passo4: faz o pedido
passo5: recebe a resposta
==8)
o que é que um serviço e um proxy têm em comum?
a interface, os métodos que implementam
==9)
porque razão é que o java RMi nas interfaces remotas tem que ter os argumentos e os resultados serializados?
porque o sistema, invocamos o método remoto e o que acontece é que é enviado um objecto que representa um pedido para o servidor, e o RMi faz a serialização dos objetos logo o pedido vai ter a identificação do método, etc, e assim tem que ser tudo serializado
==10)
só os métodos que fazem parte da interface remota é que precisam do RemoteException?
assim os outros métodos do serviço que não fazem parte da interface remota já não vão dar
==11)
naming.rebind(registration, bs);
em que:
se estabelece uma ligação TCP
no porto 1099 (porto de escuta do RMi registry)
manda-lhe uma margem para registar como o nome RMi Light bulb a referencia ao objecto Bs
==12)
rmi://192.10.10.10/xpb
o que faz quando se faz naming rebind
isto não estabelece uma ligação com um serviço
naming.lookup(rmi://192.10.10.10/xpb);
o naming.lookup no cliente para ele obter a referência para um serviço com este nome
quando se faz o lookup o que é feito é uma ligação TCP com qualquer coisa no IP no porto 1099 que é do registry e quero obter uma referência para um objecto com o nome xpb, esta referência tem interface e tem IP e porto
==13)
qual a diferença entre o método Bind e Rebind? (Bind e Rebind, tem a ver com tabelas no registry)
Com o rebind se existir é substituído senão existir ria
com o bind se não existir cria e se já existir cria uma excepção
==14)
no cliente o que é que faz o ON em bullbService.on(); sabendo que existiu
SErviceRmi bullBservice = (serviçoRmi) remoteSErvice
o cliente não faz um NEW local do objecto o que ele faz é um naming.lookup
no cliente depois vou ter um objecto que implementa a interface do serviço (on, off, …)
into é em sturb, e vai ser enviado ao fazer on, envia serializado a operação que tem que ser executada e que é o on, e o serviço recebe o pedido, executa e devolve o resutlado
==15)
qual é o aspecto comum entre proxy/sturb e o serviço?
é a interface, tem um conjunto de métodos coincidentes isto é, no serviço existe um on() e no sturb também existe um on() que na realidade envia uma mensagem para o outro lado para ligar
==16)
o que significa?
endPoint(10.20,4,128.77:53561);
10.20,4,128.77 é o IP do serviço
53561 é o porto automático, criado pelos server socket
quando o cliente faz o lookup do registry obtêm uma eferencia remota, o que se indica no lookup é o ip do registry e o porto (do registry) mas aqui é isto que eu obtenho
==17)
o que é que é comum entre o serviço (servidor) e a referência remota (Sturb, no cliente)?
é a interface implementada
o proxy não faz aquilo que é suposto o método fazerem, o que ele faz é pegar nos argumentos e envia para o servidor (Skeletton) que no servidor vai ser executado, que depois serializa e envia a resposta e o Sturb devolve a resposta ao cliente
quando o serviço é lançado (no servidor) ele regista-se no RMi registry (que é tipo um DNS) onde fica registado o IP e o porto onde pode ser encontrado o serviço
==18)
o que acontece inernamente (por baixo) no cliente RMi quando ele faz so dos métodos, por exemplo em:
bulbSErvice.isOn()
é feito um pedido de envio
aguarda resposta
o pedido é serialziado
e é devolvida a resposta
==19)
situação de dois clientes acederem ao mesmo objecto ao mesmo tempo?
o cliente através do lookup contacta o registry (TCP, 1099) e envia o pedido para o que quer
o cliente depois recebe a referência remota do objecto, que tem a interface pretendida (métodos…) e também tem o ip e porto do serviço (serviço APi)
no servidor depois de contactado cria uma thread que vai cuidar desse cliente
e se existir outro cliente vai também ser o mesmo procedimento, e no serviço (servidor) é criada outra thread
assim eu tenho que verificar se é critico os acessos concorrentes, dois clientes têm acesso a um determinado serviço, estão a aceder ao mesmos erviço e mesmos recursos, então eu terei que colocar nas classes concretas/serviços o sincronized
por exemplo:
private boolean lightOn() sincronized;
pois pode ser alterada pelos vários clientes logo estes métodos têm que ser sincronized
==20)
callbacks RMi
o cliente vai logo terminar?
no main do cliente encontra-se:
tenho uma referencia
obtive a temperatura
crio o serviço (NEW…)
registo o sensor (temperature change…)
mas a aplicação do cliente não termina porque foi criado um objecto do tipo unicast object, que tem uma thread que está à escuta no server socket e que é um serviço
==21)
o que é que isto identifica?
RMi://services.isec.pt/servicosacademicos
RMi registry, que é uma base de dados com uma tabela que tem nome e caminho remoto (dos sturbs)
em que servicosacademicos é nome do serviço
na tabela surgem referências remotas, do tipo javaRMi remote
com o método lookup, obtenho o valor correspondente aos servicosacademicos
com o método nbing, serve para apagar
com o método bing ou rebind, serve para acrescentar (bind) ou para substituir (rebind)
==22)
o que faz o openStramÎnputStream in = myURL.openStream();
faz uma ligação TCP no porto adequado no URL, envia para lá um get com o ficheiro não identificado por omissão