Programação Orientada a Objetos Programação em Redes Paulo André Castro CES-22 IEC - ITA 6. Networking Sumário 6.1 6.2 6.3 6.4 Introdução Criando um Servidor Simples usando Stream Sockets Criando um Cliente Simples usando Stream Sockets Uma Aplicação Client/Server com Stream Socket 6.5 Manipulando URLs 6.6 Lendo um arquivo em um Web Server 6.7 Segurança e Rede 6.8 Design Patterns usados nos Packages java.io e java.net 6.8.1 Creational Design Patterns 6.8.2 Structural Design Patterns Paulo André Castro CES-22 IEC - ITA 6.1 Introduction • Networking package is java.net – Socket-based communications • Applications view networking as streams of data • Connection-based protocol • Uses TCP (Transmission Control Protocol) – Packet-based communications • Individual packets transmitted • Connectionless service • Uses UDP (User Datagram Protocol) Paulo André Castro CES-22 IEC - ITA 6.2 Establishing a Simple Server Using Stream Sockets • Five steps to create a simple server in Java – ServerSocket object • Registers an available port and a maximum number of clients – Each client connection handled with Socket object • Server blocks until client connects – Sending and receiving data • OutputStream to send and InputStream to receive data • Methods getInputStream and getOutputstream – Use on Socket object – Process phase • Server and Client communicate via streams – Close streams and connections Paulo André Castro CES-22 IEC - ITA 6.5 Establishing a Simple Client Using Stream Sockets • Four steps to create a simple client in Java – Create a Socket object for the client – Obtain Socket’s InputStream and Outputstream – Process information communicated – Close streams and Socket Paulo André Castro CES-22 IEC - ITA 6.6 Client/Server Interaction with Stream Socket Connections • Client/server chat application – Uses stream sockets as described in last two sections Paulo André Castro CES-22 IEC - ITA Paulo André Castro POO ITA – Stefanini 7 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // Server.java // Set up a Server that will receive a connection from a client, send // a string to the client, and close the connection. import java.io.*; import java.net.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Server extends JFrame { private JTextField enterField; private JTextArea displayArea; private ObjectOutputStream output; private ObjectInputStream input; private ServerSocket server; private Socket connection; private int counter = 1; Listen on a ServerSocket; the connection is a Socket // set up GUI public Server() { super( super( "Server" ); Container container = getContentPane(); Paulo André Castro POO ITA – Stefanini 8 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 // create enterField and register listener enterField = new JTextField(); enterField.setEditable( false ); enterField.addActionListener( new ActionListener() { // send message to client public void actionPerformed( ActionEvent event ) { sendData( event.getActionCommand() ); enterField.setText( "" ); } } ); container.add( enterField, BorderLayout.NORTH BorderLayout.NORTH ); // create displayArea displayArea = new JTextArea(); container.add( new JScrollPane( displayArea ), BorderLayout.CENTER BorderLayout.CENTER ); setSize( 300, 300, 150 ); setVisible( true ); } // end Server constructor Paulo André Castro POO ITA – Stefanini 9 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 // set up and run server public void runServer() { // set up server to receive connections; process connections try { // Step 1: Create a ServerSocket. server = new ServerSocket( 12345, 12345, 100 ); Create ServerSocket at port 12345 with queue of length 100 while ( true ) { try { waitForConnection(); getStreams(); processConnection(); } // // // Step Step Step 2: 3: 4: Wait for a connection. Get input & output streams. Process connection. // process EOFException when client closes connection catch ( EOFException eofException ) { System.err.println( "Server terminated connection" ); } finally { closeConnection(); ++counter; } Paulo André Castro // Step 5: Close connection. POO ITA – Stefanini 10 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 } // end while } // end try // process problems with I/O catch ( IOException ioException ) { ioException.printStackTrace(); } } // end method runServer // wait for connection to arrive, then display connection info private void waitForConnection() throws IOException { Method accept waits displayMessage( "Waiting for connection\ connection\n" ); connection = server.accept(); // allow server to accept connection for connection displayMessage( "Connection " + counter + " received from: " + connection.getInetAddress().getHostName() ); Output name of } // get streams to send and receive data private void getStreams() throws IOException { Paulo André Castro POO computer that connected ITA – Stefanini 11 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 // set up output stream for objects output = new ObjectOutputStream( connection.getOutputStream() ); output.flush(); // flush output buffer to send header information // set up input stream for objects input = new ObjectInputStream( connection.getInputStream() ); displayMessage( "\nGot I/O streams\ streams\n" ); } Method flush empties output buffer and sends header information // process connection with client private void processConnection() throws IOException { // send connection successful message to client String message = "Connection successful"; successful"; sendData( message ); // enable enterField so server user can send messages setTextFieldEditable( true ); do { // process messages sent from client Paulo André Castro POO ITA – Stefanini 12 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 // read message and display it try { message = ( String ) input.readObject(); displayMessage( "\n" + message ); } // catch problems reading from client catch ( ClassNotFoundException classNotFoundException ) { displayMessage( "\nUnknown object type received" ); } Read String from client and display it } while ( !message.equals( "CLIENT>>> TERMINATE" ) ); } // end method processConnection // close streams and socket private void closeConnection() { displayMessage( "\nTerminating connection connection\ \n" ); setTextFieldEditable( false ); // disable enterField Method closeConnection closes streams and sockets try { output.close(); input.close(); connection.close(); } Paulo André Castro POO ITA – Stefanini 13 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 catch( catch( IOException ioException ) { ioException.printStackTrace(); } } // send message to client private void sendData( String message ) { // send object to client try { output.writeObject( "SERVER>>> " + message ); output.flush(); displayMessage( "\nSERVER>>> " + message ); } // process problems sending object catch ( IOException ioException ) { displayArea.append( "\nError writing object" ); } Method flush empties output buffer and sends header information } // utility method called from other threads to manipulate // displayArea in the eventevent-dispatch thread private void displayMessage( final String messageToDisplay ) { Paulo André Castro POO ITA – Stefanini 14 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 // display message from eventevent-dispatch thread of execution SwingUtilities.invokeLater( new Runnable() { // inner class to ensure GUI updates properly public void run() // updates displayArea { displayArea.append( messageToDisplay ); displayArea.setCaretPosition( displayArea.getText().length() ); } } // end inner class ); // end call to SwingUtilities.invokeLater } // utility method called from other threads to manipulate // enterField in the eventevent-dispatch thread private void setTextFieldEditable( final boolean editable ) { // display message from eventevent-dispatch thread of execution SwingUtilities.invokeLater( new Runnable() { // inner class to ensure GUI updates properly Paulo André Castro POO ITA – Stefanini 15 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 } public void run() // sets enterField's editability { enterField.setEditable( editable ); } } // end inner class ); // end call to SwingUtilities.invokeLater } public static void main( String args[] ) { Server application = new Server(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE JFrame.EXIT_ON_CLOSE ); application.runServer(); } // end class Server Paulo André Castro POO ITA – Stefanini 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // Client.java // Client that reads and displays information sent from a Server. import java.io.*; import java.net.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Client extends JFrame { private JTextField enterField; private JTextArea displayArea; private ObjectOutputStream output; private ObjectInputStream input; private String message = ""; ""; private String chatServer; private Socket client; The client is a Socket // initialize chatServer and set up GUI public Client( String host ) { super( super( "Client" ); chatServer = host; // set server to which this client connects Container container = getContentPane(); Paulo André Castro POO ITA – Stefanini 17 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 // create enterField and register listener enterField = new JTextField(); enterField.setEditable( false ); enterField.addActionListener( new ActionListener() { // send message to server public void actionPerformed( ActionEvent event ) { sendData( event.getActionCommand() ); enterField.setText( "" ); } } ); container.add( enterField, BorderLayout.NORTH BorderLayout.NORTH ); // create displayArea displayArea = new JTextArea(); container.add( new JScrollPane( displayArea ), BorderLayout.CENTER BorderLayout.CENTER ); setSize( 300, 300, 150 ); setVisible( true ); Paulo André Castro POO ITA – Stefanini 18 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 } // end Client constructor // connect to server and process messages from server private void runClient() { // connect to server, get streams, process connection try { connectToServer(); // Step 1: Create a Socket to make connection getStreams(); // Step 2: Get the input and output streams processConnection(); // Step 3: Process connection } // server closed connection catch ( EOFException eofException ) { System.err.println( "Client terminated connection" ); } // process problems communicating with server catch ( IOException ioException ) { ioException.printStackTrace(); } finally { closeConnection(); // Step 4: Close connection } Paulo André Castro POO ITA – Stefanini 19 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 } // end method runClient // connect to server private void connectToServer() throws IOException { displayMessage( "Attempting connection\ connection\n" ); // create Socket to make connection to server client = new Socket( InetAddress.getByName( chatServer ), 12345 ); // display connection information displayMessage( "Connected to: " + client.getInetAddress().getHostName() ); } Create a client that will connect with port 12345 on the server Notify the user that we have connected // get streams to send and receive data private void getStreams() throws IOException { // set up output stream for objects output = new ObjectOutputStream( client.getOutputStream() ); output.flush(); // flush output buffer to send header information // set up input stream for objects input = new ObjectInputStream( client.getInputStream() ); Paulo André Castro POO Get the streams to send and receive data ITA – Stefanini 20 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 displayMessage( "\nGot I/O streams\ streams\n" ); } // process connection with server private void processConnection() throws IOException { // enable enterField so client user can send messages setTextFieldEditable( true ); do { // process messages sent from server // read message and display it try { message = ( String ) input.readObject(); displayMessage( "\n" + message ); } // catch problems reading from server catch ( ClassNotFoundException classNotFoundException ) { displayMessage( "\nUnknown object type received" ); } Read String from client and display it } while ( !message.equals( "SERVER>>> TERMINATE" ) ); } // end method processConnection Paulo André Castro POO ITA – Stefanini 21 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 // close streams and socket private void closeConnection() { displayMessage( "\nClosing connection" ); setTextFieldEditable( false ); // disable enterField try { output.close(); input.close(); client.close(); } catch( catch( IOException ioException ) { ioException.printStackTrace(); } Method closeConnection closes streams and sockets } // send message to server private void sendData( String message ) { // send object to server try { output.writeObject( "CLIENT>>> " + message ); output.flush(); displayMessage( "\nCLIENT>>> " + message ); } Paulo André Castro POO Method flush empties output buffer and sends header information ITA – Stefanini 22 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 // process problems sending object catch ( IOException ioException ) { displayArea.append( "\nError writing object" ); } } // utility method called from other threads to manipulate // displayArea in the eventevent-dispatch thread private void displayMessage( final String messageToDisplay ) { // display message from GUI thread of execution SwingUtilities.invokeLater( new Runnable() { // inner class to ensure GUI updates properly public void run() // updates displayArea { displayArea.append( messageToDisplay ); displayArea.setCaretPosition( displayArea.getText().length() ); } } // end inner class ); // end call to SwingUtilities.invokeLater } Paulo André Castro POO ITA – Stefanini 23 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 // utility method called from other threads to manipulate // enterField in the eventevent-dispatch thread private void setTextFieldEditable( final boolean editable ) { // display message from GUI thread of execution SwingUtilities.invokeLater( new Runnable() { // inner class to ensure GUI updates properly public void run() // sets enterField's editability { enterField.setEditable( editable ); } } // end inner class ); // end call to SwingUtilities.invokeLater } public static void main( String args[] ) { Client application; Paulo André Castro POO ITA – Stefanini 24 203 if ( args.length == 0 ) 204 application = new Client( "127.0.0.1" ); 205 else 206 application = new Client( args[ 0 ] ); 207 208 application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE JFrame.EXIT_ON_CLOSE ); 209 application.runClient(); 210 } 211 212 } // end class Client Paulo André Castro POO Create a client to connect to the localhost Connect to a host supplied by the user ITA – Stefanini 25 Exercício • Estabeleça um chat com um colega através da porta 8189. Paulo André Castro CES-22 IEC - ITA 6.3 Reading a File on a Web Server • Swing GUI component JEditorPane – Can display simple text and HTML formatted text – Can be used as a simple Web browser • Retrieves files from a Web server at a given URI Paulo André Castro CES-22 IEC - ITA 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // ReadServerFile.java // Use a JEditorPane to display the contents of a file on a Web server. import java.awt.*; import java.awt.event.*; import java.net.*; import java.io.*; import javax.swing.*; import javax.swing.event.*; public class ReadServerFile extends JFrame { private JTextField enterField; private JEditorPane contentsArea; // set up GUI public ReadServerFile() { super( super( "Simple Web Browser" ); File displayed in JEditorPane Container container = getContentPane(); // create enterField and register its listener enterField = new JTextField( "Enter file URL here" ); enterField.addActionListener( new ActionListener() { Paulo André Castro CES-22 IEC - ITA 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 // get document specified by user public void actionPerformed( ActionEvent event ) { getThePage( event.getActionCommand() ); } } // end inner class ); // end call to addActionListener container.add( enterField, BorderLayout.NORTH BorderLayout.NORTH ); // create contentsArea and register HyperlinkEvent contentsArea = new JEditorPane(); contentsArea.setEditable( false ); contentsArea.addHyperlinkListener( new HyperlinkListener() { Register a HyperlinkListener to listener handle HyperlinkEvents // if user clicked hyperlink, go to specified page public void hyperlinkUpdate( HyperlinkEvent event ) { if ( event.getEventType() == HyperlinkEvent.EventType.ACTIVATED HyperlinkEvent.EventType.ACTIVATED ) getThePage( event.getURL().toString() ); } Paulo André Castro Method hyperlinkUpdate called when hyperlink clicked Determine type of hyperlink Get URL of hyperlink and retrieve page CES-22 IEC - ITA 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 } // end inner class ); // end call to addHyperlinkListener container.add( new JScrollPane( contentsArea ), BorderLayout.CENTER BorderLayout.CENTER ); setSize( 400, 400, 300 ); setVisible( true ); } // end constructor ReadServerFile // load document private void getThePage( String location ) { // load document and display location try { contentsArea.setPage( location ); enterField.setText( location ); } catch ( IOException ioException ) { JOptionPane.showMessageDialog( this, this, "Error retrieving specified URL", URL", "Bad URL", URL", JOptionPane.ERROR_MESSAGE JOptionPane.ERROR_MESSAGE ); } Method setPage downloads document and displays it in JEditorPane } // end method getThePage Paulo André Castro CES-22 IEC - ITA 78 79 80 81 82 83 84 85 public static void main( String args[] ) { ReadServerFile application = new ReadServerFile(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } } // end class ReadServerFile Paulo André Castro CES-22 IEC - ITA Exercício • Incluir um barra de ferramentas acima do campo de edição da URL com os botões “Home” (Página Inicial) e “Atualizar” e seus respectivos comportamentos • Criar botão “Voltar” e seu respectivo comportamento Paulo André Castro CES-22 IEC - ITA Desafio • Criar novas versões das classes de Client e Server do package ClientServer tais que seja possível estabelecer um chat com múltiplos clientes. Cada cliente deve ser identificado Client1, client2,etc. de acordo com a ordem de conexão ao servidor. • Ao ser enviado mensagem de um cliente qualquer todos os clientes e servidor devem receber tal mensagem com a identificação ClientX>>> • O servidor não precisa ter uma interface gráfica Paulo André Castro CES-22 IEC - ITA