Explorar E-books
Categorias
Explorar Audiolivros
Categorias
Explorar Revistas
Categorias
Explorar Documentos
Categorias
24
Redes
2005 by Pearson Education do Brasil
OBJETIVOS
Neste captulo, voc aprender: Como entender a tecnologia de redes do Java com URLs, sockets e datagramas. Como implementar aplicativos de rede de Java utilizando sockets e datagramas. Como implementar clientes e servidores Java que se comunicam entre si. Como implementar aplicativos colaborativos baseados em rede. Como construir um servidor multiencadeado.
Introduo Manipulando URLs Lendo um arquivo em um servidor Web Estabelecendo um servidor simples utilizando sockets de fluxo Estabelecendo um cliente simples utilizando sockets de fluxo Interao cliente/servidor com conexes de socket de fluxo Interao cliente/servidor sem conexo com datagramas Jogo-da-velha cliente/servidor que utiliza um servidor com multithread Segurana e redes 24.10.1 24.10.2 DeitelMessengerServer e classes de suporte Cliente DeitelMessenger e classes de suporte
24.11 Concluso
24.1 Introduo
O pacote de rede o java.net:
Comunicaes baseadas em fluxo:
Os aplicativos visualizam a rede como fluxos de dados. Protocolo baseado em conexo. Utilizam o popular TCP (Transmission Control Protocol).
1 2 3 4 5 6 7 8 9 10 11 12 13
<html> <title>Site <title>Site Selector</title> Selector</title> <body> <applet code = "SiteSelector.class" width = "300" height = "75"> "75"> <param name = "title0" value = "Java Home Page"> Page"> <param name = "location0" value = "http://java.sun.com/" "http://java.sun.com/"> sun.com/"> <param name = "title1" value = "Deitel"> "Deitel"> <param name = "location1" value = "http://www.deitel.com/"> "http://www.deitel.com/"> <param name = "title2" value = "JGuru"> "JGuru"> <param name name = "location2" value = "http://www.jGuru.com/"> "http://www.jGuru.com/"> <param name = "title3" value = "JavaWorld"> "JavaWorld"> <param name = "location3" value = "http://www.javaworld.com/"> "http://www.javaworld.com/"> </applet>
Resumo
SiteSelector.html
Declara tags param Linhas 5-12 para a applet; cada parmetro tem um name e um value
14 </body> 15 </html>
Figura 24.1
SiteSelector.
1 2 3 4 5 6 7 8 9
// Fig. 24.2: SiteSelector.java // Esse programa carrega um documento de um URL. URL. import java.net.MalformedURLException; import import import java.net.URL; java.util.HashMap; java.util.ArrayList;
10
Resumo
SiteSelector.java
import import java.awt.BorderLayout; import java.applet.AppletContext; import javax.swing.JApplet; 10 import javax.swing.JLabel; 11 import javax.swing.JList; 12 import javax.swing.JScrollPane; 13 import javax.swing.event.ListSelectionEvent; 14 import javax.swing.event.ListSelectionListener; 15
16 public class SiteSelector extends JApplet 17 { 18 private HashMap< Object, URL > sites; // nomes e URLs de site 19 private ArrayList< String > siteNames; // nomes de site 20 lista private JList siteChooser; // list a de sites a escolher 21 22 23 24 25 26 27 28 29 30 // l parmetros de HTML e configura a GUI public void init() { sites = new HashMap< Object, URL >(); // cria cria HashMap siteNames = new ArrayList< String >(); // cria cria ArrayList // obtm obtm parmetros parmetros do documento HTML getSitesFromHTMLParameters();
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
// cria componentes GUI e interface de layout add( new JLabel( "Choose a site to browse" ), BorderLayout.NORTH ); siteChooser = new JList( siteNames.toArray() ); // preenche preenche JList siteChooser.addListSelectionListener( siteChooser.addListSelectio nListener( new ListSelectionListener() // classe interna an annima { // vai ao site selecionado pelo usurio public void valueChanged( ListSelectionEvent event ) { // obtm o nome do site selecionado Object object = siteChooser.getSelectedValue();
11
Resumo
SiteSelector.java
(2 de 5) Linhas 39-52
);
Quando o usurio seleciona um dos sites Linha 45 listados no siteChooser, o // utiliza o nome do site para localizar o URL Web correspondente URL newDocument = sites.get( object ); 48 programa chama osite mtodo Passa o nome doLinha selecionado (a valueChanged chave) para o mtodo Hashtable // obtm continer de applets applets Linha 51 get, que localiza e retorna uma AppletContext browser = getAppletContext(); Obtm uma referncia a um referncia de URL correspondente (o objeto AppletContext que // instrui o continer de applets a mudar as pginas valor). representa o continer de browser.showDocument( browser.showDocument( newDocument ); Exibe na janela atual do navegador applets } // fim do mtodo valueChanged o recurso associado com o URL } // fim da classe interna annima newDocument // fim da chamada para addListSelectionListener
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
// obtm parmetros do documento HTML private void getSitesFromHTMLParameters() { String title; // ttulo do site String location; // localizao do site URL url; // URL da localizao int counter = 0; // conta nmero de sites title = getParameter( "title" + counter ); // obtm o primeiro ttulo do site // faz um loop at no haja mais parmetros no documento HTML while ( title != null ) { Utiliza o mtodo Applet // obtm a localizao do site getParameter location = getParameter( "location" + counter );
12
Resumo
SiteSelector.java
(3 de 5) Linha 67 Linha 73
para obter o ttulo do Linha 77 Applet site Web Utiliza o mtodo getParameter para try // coloca ttulo/URL no HashMap e ttulo na ArrayList Linhas 81-84 obter a localizao do site { Web url = new URL( location location ); // converte a localizao em URL Utiliza a location como sites.put( title, url ); // coloca ttulo/URL no HashMap o valor de um novo objeto siteNames.add( title ); // coloca o ttulo na ArrayList URL } // fim do try
catch ( MalformedURLException MalformedURLException urlException ) { urlException.printStackTrace(); } // fim do catch
Se a location passada para o construtor de IURL for invlida, o construtor de URL lanar uma MalformedURLException
86 87 88 89
counter++; title = getParameter( "title" + counter ); // obtm o prximo ttulo do site } // fim do while } // fim do mtodo getSitesFromHTMLParameters
13
Resumo
Utiliza o mtodo Applet SiteSelector.java getParameter para obter o ttulo do (4 de 5) prximo site Linha 87 Sada do programa
14
Resumo
SiteSelector.java
(5 de 5) Sada do programa
15
16
17
1 2 3 4 5 6
// Fig. 24.3: ReadServerFile.java Web. . // Usa um JEditorPane para exibir o contedo de um arquivo em um servidor Web import java.awt.BorderLayout; import java.awt.event.ActionEvent;
18
Resumo
ReadServerFile .java
import java.awt.event.ActionListener; import java.io.IOException; java.io.IOException; 7 import javax.swing.JEditorPane; 8 import javax.swing.JFrame; 9 import javax.swing.JOptionPane; 10 import javax.swing.JScrollPane;
11 import javax.swing.JTextField; 12 import javax.swing.event.HyperlinkEvent; 13 import javax.swing.event.HyperlinkListener; javax.swing.event.HyperlinkListener; Linha 18 14 15 public class ReadServerFile extends JFrame 16 { 17 private JTextField enterField; // JTextField para inserir nome do site 18 private JEditorPane contentsArea; // para exibir site da Web Declara o JEditorPane 19 contentsArea, que ser 20 // configura a GUI utilizado para exibir o 21 public ReadServerFile() contedo do arquivo 22 { 23 super( super ( "Simple Web Browser" ); 24
Importa JEditPane do pacote javax.swing, importa HyperlinkEvent (1 de 3) e HyperlinkListener do pacote javax.swing.event Linhas 7, 12 e 13
25 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 53 54
// cria o enterField e registra seu ouvinte enterField = new JTextField( "Enter file URL here" ); enterField.addActionListener( new ActionListener() { // obtm o documento especificado especificado pelo usurio public void actionPerformed( ActionEvent event ) { getThePage( event.getActionCommand() ); } // fim do mtodo actionPerformed } // fim da classe interna interna ); // fim da chamada para addActionListener add( enterField, BorderLayout.NORTH );
19
Resumo
ReadServerFile .java
(2 de 3) Linha 40
Linha 41 Cria um contentsArea = new JEditorPane(); // cria cria contentsArea Linhas 42-53 Configura a propriedade JEditorPane contentsArea.setEditable( false ); Registra um o construtor editvel JEditorPane utilizando contentsArea.addHyperlinkListener( Linhas 46-51 HyperlinkListener para tratar como false sem argumento new HyperlinkListener() HyperlinkEvents que ocorrem { Linhas 48-49 // se usurio clicou clicou no hyperlink, hyperlink, vai para a pgina especif especificada pecificada quando o usurio em um O clica mtodo public void hyperlinkUpdate( HyperlinkEvent event ) hyperlink no JEditorPane hyperlinkUpdate Linha 50 { Utiliza o mtodo chamado quando um if ( event.getEventType() == HyperlinkEvent HyperlinkEvent ocorre HyperlinkEvent.EventType.ACTIVATED ) getEventType para getThePage( event.getURL().toString() ); determinar o tipo do } // fim do mtodo hyperlinkUpdate } // fim da classe interna HyperlinkEvent Utiliza o mtodo ); // fim da chamada para addHyperlinkListener HyperlinkEvent getURL para obter o URL representado pelo hyperlink.
2005 by Pearson Education do Brasil
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
add( new JScrollPane( contentsArea ), BorderLayout.CENTER ); setSize( 400, 400, 300 ); // configura o tamanho da janela setVisible( true ); // mostra a janela } // fim do construtor ReadServerFile // carrega o documento documento private void getThePage( String location ) { try // carrega o documento documento e exibe a localizao localizao { contentsArea.setPage( location ); // configura a pgina location enterField.setText( loca tion ); // configura o texto } // fim do try catch ( IOException ioException ) { JOptionPane.showMessageDialog( this this, , URL", , "Error retrieving specified URL", URL", "Bad URL" JOptionPane.ERROR_MESSAGE JOptionPan e.ERROR_MESSAGE ); } // fim do catch } // fim do mtodo getThePage } // fim da class classe e ReadServerFile
20
Resumo
ReadServerFile .java
(3 de 3) Invoca o mtodo JEditorPane setPage Linha 65 para fazer o download do documento especificado por location e exibi-lo no JEditPane
1 2 3 4 5 6 7 8 9 10 11
// Fig. 24.4: ReadServerFileTest.java // Cri Cria e inicia um ReadServerFile. import javax.swing.JFrame; public class ReadServerFileTest { public static void main( String args[] ) { ReadServerFile application = new ReadServerFile(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } // fim do main
21
Resumo
ReadServerFileTest .java
(1 de 2) Sada do programa
22
Resumo
ReadServerFileTest .java
(2 de 2) Sada do programa
23
24
25
26
27
28
29
30
31
32
33
O cliente ou o servidor fecha a conexo. O servidor espera que o prximo cliente se conecte.
1 2 3 4 5 6 7 8 9
// Fig. 24.5: Server.java // Configura uma classe Server que receber uma conexo de um cliente, envia // uma string ao cliente e fecha a conexo. conexo. import java.io.EOFException; import java.io.IOException; import java.io.ObjectInputStream; java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket;
34
Resumo
Server.java
10 import java.awt.BorderLayout; 11 import java.awt.event.ActionEvent; 12 import java.awt.event.ActionListener; 13 import javax.swing.JF javax.swing.JFrame; rame; 14 import javax.swing.JScrollPane; 15 import javax.swing.JTextArea; 16 import javax.swing.JTextField; 17 import javax.swing.SwingUtilities; 18
(1ede 8) Importa ServerSocket Socket do pacote java.net Linhas 8-9 Linha 25 Linha 26
19 public class Server extends JFrame 20 { 21 private JTextField enterField; // insere a mensagem do usurio 22 private JTextArea displayArea; // exibe informaes para o usurio 23 private ObjectOutputStream output; // gera fluxo de sada para o cliente 24 25 26 27 28 private ObjectInputStream input; // gera fluxo de entrada Declara a partir do cliente ServerSocket server private ServerSocket server; // socket de servidor Declara connection que esperaSocket a conexo do cliente private Socket connection; // conexo com o cliente private int counter = 1; // contador do nmero de conexes
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
// configura a GUI public Server() { super( super( "Server" ); enterField = new JTextField(); // cri cria enterField enterField.setEditable( false ); enterField.addActionListener( new ActionListener() { // envia message messagem para o cliente cliente public void actionPerformed( ActionEvent event ) { sendData( event.getActionCommand() ); enterField.setText( enterField.setText( "" ); } // fim do mtodo actionPerformed } // fim da classe interna an annima nima ); // fim da chamada para addActionListener add( enterField, BorderLayout.NORTH ); displayArea = new JTextArea(); // cr cri ia displayArea add( new JScrollPane( displayArea ), BorderLayout.CENTER ); setSize( 300, 300, 150 ); // configura o tamanho da janela setVisible( true ); // mostra a janela } // fim do construt construtor Server
35
Resumo
Server.java
(2 de 8)
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
// configura e executa o servidor public void runServer() { try // configura o servidor para receber conexes; processa as conexes { server = new ServerSocket( 12345, 12345, 100 ); // cria cria ServerSocket while ( true ) { try { waitForConnection(); // espera uma conexo getStreams(); // obtm fluxos de entrada e sada processConnection(); processa conexo processConne ction(); // process a cone xo } // fim do try catch ( EOFException eofException ) { displayMessage( "\nServer terminated connection" ); } // fim do catch
36
Resumo
Server.java
(3 de 8) na porta Cria o ServerSocket 12345 com uma fila de Linha 62 comprimento 100 Linha 68 Espera uma conexo Depois de cliente a conexo ser de um Linha 69 Envia a mensagem estabelecida, obtm de conexo inicial ao cliente e referncias aos fluxos Linha 70 processa todas as para a conexo mensagens recebidas do cliente
finally { closeConnection(); // fecha conexo conexo counter++; } // fim do finally } // fim do while } // fim do try IOException catch ( IOExceptio n ioException ) { ioException.printStackTrace(); } // fim do catch } // fim do mtodo runServer
37
Resumo
Server.java
(4 de 8) Linha 93
Linha 95 Gera o nome de host do computador que Linha 102 criou a conexo utilizando os mtodos Utiliza o mtodo ServerSocket // espera que a conexo chegue e, informaes sobre a conexoe o mtodo e, ento, ento, exibe Socket getInetAddress accept para esperar uma conexo Linha de 103 private void waitForConnection() waitForConnection() throws IOException InetAddress um getHostName cliente {
displayMessage( "Waiting for connection\ connection\n" ); connection = server.accept(); // permite que o servido aceite conexo conexo displayMessage( "Connection " + counter + " received from: " + connection.getInetAddress().getHostName() ); } // fim do mtodo waitForConnection // obtm fluxos para enviar e receber dados O mtodo flush esvazia o buffer de para inicializar utiliza-o private void getStreams() throws IOException sada e envia as informaes de ObjectOutputStream { cabealho fluxo // configura o flu xo de sada para objetos output = new ObjectOutputStream( connection.getOutputStream() ); output.flush(); // esvazia buffer de sada p/ enviar as informaes de cabealho
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
// configura o fluxo de entrada para objetos input = new ObjectInputStream( connection.getInputStream() ); displayMessage( "\nGot I/O streams\ streams\n" ); } // fim do mtodo getStreams
38
Resumo
(5 de 8)
// processa processa conexo com cliente cliente private void processConnection() throws IOException {
String message = "Connection successful"; successful"; sendData( message ); // envia uma mensagem de conexo bembem-sucedida // ativa enterField enterField de modo que usurio do servidor possa enviar mensagens setTextFieldEditable( true ); do // processa processa mensagens enviadas do cliente cliente {
try // l messagem messagem e a exibe { message = ( String ) input.readObject(); // l nova messagem messagem messagem displayMessage( "\n" + message ); // exibe messag em } // fim do try catch ( ClassNotFoundException classNotFoundException ) { displayMessage( "\nUnknown object type received" ); } // fim do catch
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 153 154 155 156 157 158 159 160 161
} while ( !message.equals( "CLIENT>>> TERMINATE" ) ); } // fim do mtodo processConnection // fecha os fluxos e o socket private void closeConnection() {
39
Resumo
Server.java
displayMessage( "\nTerminating conn connection ection\ ection\n" ); setTextFieldEditable( false ); // desativa desativa enterField try { output.close(); // fecha o fluxo de sada input.close(); // fecha o fluxo de entrada connection.close(); connectio n.close(); // fecha o socket } // fim do try catch ( IOException ioException ) { ioException.printStackTrace(); } // fim do catch } // fim do mtodo closeConnection // env envia messagem cliente ia messag em para o client e
Linhas 136-151 Linha 145 Linha 158 Invoca o mtodo Socket close para fechar o socket
private void sendData( String message ) { try // envia objeto objeto para o cliente cliente { output.writeObject( "SERVER>>> " + message ); output.flush(); // esvazia sada para o cliente displayMessage( "\nSERVER>>> " + message ); } // fim do try
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
catch ( IOException ioException ) { displayArea.append( "\nError writing object" ); } // fim do catch } // fim do mtodo sendData
40
Resumo
Server.java
// manipula displayArea na thread de despacho de eventos eventos private void displayMessage( final String messageToDisplay ) { SwingUtilities.invokeLater( new Runnable() { public void run() // atualiza displayArea { displayArea.append( messageToDisplay ); // anexa messagem messagem } // fim do mtodo run } // fim da classe interna annima ); // fim da chamada para SwingUtilities.invokeLater } // fim do mtodo displayMessage
(7 de 8)
182 183 184 185 186 187 188 189 190 191 192 193 194
// manipula o enterField na thread de despacho de eventos private void setTextFieldEditable( final boolean editable ) { SwingUtilities.invokeLater( new Runnable() { public public void run() // configura a editabilidade do enterField { enterField.setEditable( editable ); } // fim do mtodo run } // fim da classe inner ); // fim da chamada para SwingUtilities.invokeLater SwingUtilities.invokeLater } // fim do mtodo setTextFieldEditable
41
Resumo
Server.java
(8 de 8)
1 2 3 4 5 6 7 8 9 10 11 12
// Fig. 24.6: ServerTest.java // Testa Testa o aplicativo Server. import javax.swing.JFrame; public class ServerTest { public static void main( String args[] ) { Server application = new Server(); // cria cria o servidor servidor application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); application.runServer(); // execut executa o aplicativo aplicativo do servidor } // fim do main
42
Resumo
ServerTest.java
43
44
45
1 2 3 4 5 6 7 8 9
// Fig. 24.7: Client.java Servidor. . // Cliente que l e exibe as informaes enviadas a partir de um Servidor import java.io.EOFException; import java.io.IOException; import import import im port import import java.io.ObjectInputStream; java.io.ObjectOutputStream; java.net.InetAddress; java.net.Socket; java.awt.BorderLayout;
46
Resumo
Client.java
(1 de 7)
10 import java.awt.event.ActionEvent; 11 import java.awt.event.ActionListener; 12 import javax.swing.JFrame; 13 import javax.swing.JScrollPane; 14 impor import t javax.swing.JTextArea; 15 import javax.swing.JTextField; 16 import javax.swing.SwingUtilities; 17 18 public class Client extends JFrame 19 { 20 private JTextField enterField; // insere informaes fornecidas pelo usurio 21 private JTextArea displayArea; // exibe informaes para o usurio 22 private ObjectOutputStream output; // gera o fluxo de sada para o servidor 23 24 25 26 27 private ObjectInputStream input; // gera o fluxo de entrada do servidor private String message = ""; ""; // messagem messagem do servido servidor idor private String chatServer; // servidor de host para esse aplicativo private Socket client; // socket para comunicao comunicao com o servidor
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 53 54 55 56 57
// inicializa chatServer e configura a GUI public Client( String host ) { super( super( "Client" ); chatServer = host; // configura o servidor ao qual esse cliente se conecta enterField = new JTextField(); JTextField(); // cria enterField enterField.setEditable( false ); enterField.addActionListener( new ActionListener() { // envia men mensagem sagem para o servidor public void actionPerformed( actionPerformed( ActionEvent event ) { sendData( event.getActionCommand() ); enterField.setText( "" ); } // fim do mtodo actionPerformed } // fim da classe interna annima ); // fim da chamada para addActionListener add( enterField, BorderLayout.NORTH ); displayArea = new JTextArea(); // cria cria displayArea add( new JScrollPane( displayArea ), BorderLayout.CENTER ); setSize( 300, 300, 150 ); // configura o tamanho da janela setVisible( true ); // mostra a janela } // fim do construtor Client
47
Resumo
Client.java
(2 de 7)
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
// conectaconecta-se ao servidor e processa as mensagens a partir do servidor public void runClient() { conectatry // conecta -se ao servidor, obtm fluxos, processa a conexo { Socket connectToServer(); // cria um Soc ket para fazer a conexo getStreams(); // obtm os fluxos de entrada e sada processConnection(); // processa processa a conexo } // fim do try catch ( EOFException eofException ) { displayMessage( displa yMessage( "\nClient terminated connection" ); } // fim do catch catch ( IOException ioException ) { ioException.printStackTrace(); } // fim do catch finally { closeConnection(); c loseConnection(); // fecha a conexo } // fim do finally } // fim do mtodo runClient // conect conectect-se ao servidor private void connectToServer() throws IOException { "Attempting displayMessage( "Attemptin g connection\ connection\n" );
48
Resumo
Client.java
(3 de 7)
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
// cria Socket fazer a conexo ao servidor client = new Socket( InetAddress.getByName( chatServer ), 12345 );
49
Cria um Socket Utiliza o que mtodo static // exibe informaes sobre a conexo getByName ser conectado portade para obter um displayMessage( "Connected to: " + objeto InetAdress que contm o 12345 no servidor client.getInetAddress().getHostName() client.getInetAddress().getHostName() ); Client.java endereo IP especificado como um Exibe uma mensagem que } // fim do mtodo connectToServer (4 de 7) argumento de linha de comando para indica o nome Obtm OutputStream de Socket e de // obtm fluxos para enviar e receber dados a aplicao computador O mtodo flush esvazia o buffer de utiliza-o para inicializar Linha 87do servidor private void getStreams() throws IOException ao qual o cliente se sada e envia as informaes de ObjectOutputStream { Linhas 90-91 conectou cabealho // configura o fluxo de sada para objetos Linha 98 output = new ObjectOutputStream( client.getOutputStream() );
output.flush(); output.flush(); // esvazia buffer de sada enviar as informaes de cabealho // configura o fluxo de entrada para objetos input = new ObjectInputStream( ObjectInputStream( client.getInputStream() ); displayMessage( "\nGot I/O streams\ streams\n" ); } // fim do mtodo getStreams // processa processa conexo com servido servidor idor private void processConnection() throws IOException { // ativa enterField para que o usurio cliente possa enviar men mensagens sagens setTextFieldEditable( true );
Resumo
Linha 99
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
do // processa processa men mensag ensagens sagens enviadas do servidor { try // l mensag ensagem sagem e a exibe { message = ( String ) input.readObject(); // l nova mensagem displayMessage( "\n" + message message ); // exibe mensagem } // fim do try catch ( ClassNotFoundException classNotFoundException ) { displayMessage( "\nUnknown object type received" ); } // fim do catch } while ( !message.equals( "SERVER>>> TERMINATE" ) ); } // fim do mtodo processConnection // fecha fluxos e socket private void closeConnection() { displayMessage( "\nClosing connection" ); setTextFieldEditable( false ); // disativa disativa enterField try { output.close(); // fecha fluxo de sada input.close(); // fecha o fluxo de entrada client.close(); // fecha socket } // fim do try
50
Resumo
Client.java
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
catch ( IOException ioException ) { ioException.printStackTrace(); } // fim do catch } // fim do mtodo closeConnection // envia men mensagem sagem para o servidor private void sendData( sendData( String message ) { objeto try // envia obje to para o servidor { output.writeObject( "CLIENT>>> " + message ); output.flush(); // esvazia os dados para sada displayMessage( "\nCLIENT>>> " + message ); } // fim do try catch ( IOException ioException ) { displayArea.append( "\nError writing object" ); } // fim do catch } // fim do mtodo sendData
51
Resumo
Utiliza o mtodo ObjectOutputStream (6 de 7) writeObject para enviar uma String ao servidor Linha 151
Client.java
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
// manipula a displayArea na thread de despacho de eventos private void displayMessage( final String messageToDisplay ) { SwingUtilities.invokeLater( new Runnable() { public public void run() // atualiza displayArea { displayArea.append( messageToDisplay ); } // fim do mtodo run } // fim da classe interna annima ); // fim da chamada para SwingUtilities.invokeLater SwingUtilities.invokeLater } // fim do mtodo displayMessage // manipula o enterField na thread de despacho de eventos private void setTextFieldEditable( final boolean editable ) { SwingUtilities.invokeLater( SwingUtilities.invokeLater( new Runnable() { public void run() // configura a editabilidade do enterField { enterField.setEditable( editable );
52
Resumo
Client.java
(7 de 7)
} // fim do mtodo run } // fim da classe interna annima 186 ); // fim da chamada para SwingUtilities.invokeLater 187 } // fim do mtodo setTextFieldEditable 188 } // fim da classe Client
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// Fig. 24.8: ClientTest.java // Testa Testa a classe Client. import javax.swing.JFrame; public class ClientTest { public static void main( String args[] ) { Client application; // declara declara o aplicativo cliente cliente // se no houver nenhum argumento de linha de comando if ( args.length == 0 ) application = new Client( "127.0.0.1" ); // conectaconecta-se ao host local else application = new Client( args[ 0 ] ); // usa usa argumentos argumentos p/ p/ se conectar conectar
53
Resumo
ClientTest.java
(1 de 2) Sada do programa
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 18 application.runClient(); // executa o aplicativo cliente cliente 19 } // fim do main 20 } // fim da classe ClientTest
54
Resumo
ClientTest.java
(2 de 2) Sada do programa
55
1 2 3 4 5 6 7 8 9
// Fig. 24.9: Server.java // Servidor que recebe e envia pacotes de/para um cliente. import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; java.awt.BorderLayout; import java.awt.Bo rderLayout; import javax.swing.JFrame;
56
Resumo
Server.java
(1 de 4) Linha 16
import javax.swing.JScrollPane; 10 import javax.swing.JTextArea; 11 import javax.swing.SwingUtilities; 12 13 public class Server extends JFrame 14 { 15 16 17 18 19 20 21 22 23 24 25 26 27 displayArea = new JTextArea(); // cr cri ia displayArea add( new JScrollPane( displayArea ), BorderLayout.CENTER ); 400, setSize( 400 , 300 ); // configura o tamanho da janela setVisible( true ); // mostra a janela // configura a GUI e o DatagramSocket public Server() { super( super ( "Server" ); private JTextArea displayArea; // exibe pacotes recebidos private DatagramSocket socket; // socket para se conectar ao clien cliente
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
try // cri cria DatagramSocket para enviar e receber pacotes { socket = new DatagramSocket( 5000 ); } // fim do try catch ( SocketException socketException ) { socketException.printStackTrace(); socketException.printStackTrace(); System.exit( 1 ); } // fim do catch } // fim do construtor Server
57
Utiliza o construtor DatagramSocket que recebe um argumento de nmero da porta inteiro para vincular o servidor a Server.java uma porta em que possa receber (2 de 4) pacotes dos clientes Linha 30 Linhas 47-48 Linha 50
Resumo
// espera pacotes chegarem, chegarem, exibe dados e ecoa o pacote para o cliente public void waitForPackets() { while ( true ) {
try // recebe recebe pacote pacote, cote, exibe contedo, contedo, retorna retorna cpia para o cliente { byte data[] = new byte[ 100 ]; // configura o pacote Cria um DatagramPacket DatagramPacket receivePacket = em que um pacote de new DatagramPacket( data, data.length ); socket.receive( receivePacket ); // espera receber
informaes recebido pode ser o pacote armazenado Utiliza o mtodo DatagramSocket receive para esperar um pacote chegar ao servidor
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 78 79 80
Utiliza o mtodo Utiliza o mtodo DatagramPacket Utiliza o mtodo DatagramPacket getPort getAddress para obter o "\ "\nLength: " + receivePacket.getLength() + DatagramPacket para obter o nmero da porta por do "\nContaining:\ nContaining:\n\t" + new String( receivePacket.getData(), receivePacket.getData(), nome de host do computador Server.java getLength para obter ohost meio da qual computador 0, receivePacket.getLength() ) ); qual oo pacote foi enviado (3 4) dados nmero de bytes dos enviou ode pacote sendPacketToClient( receivePacket ); // envia pacote para o cliente enviado Linha 54 } // fim do try Utiliza o mtodo DatagramPacket catch ( IOException ioException ) 55 bytes getData para obter umLinha array de { contendo os dados displayMessage( ioException.toString() + "\n" ); Linha 56
ioException.printStackTrace(); } // fim do cat catch ch } // fim do while } // fim do m mtodo todo waitForPackets
// exibe informa informaes do pacote recebido displayMessage( "\nPacket received:" + "\ " \nFrom host: " + receivePacket.getAddress() + "\nHost port: " + receivePacket.getPort() +
58
Resumo
// ec ecoa pacote para o cliente private void sendPacketToClient( DatagramPacket receivePacket ) throws IOException Cria um DatagramPacket, { displayMessage( "\n\nEcho data to client..."
// cri cria pacote a enviar DatagramPacket sendPacket = new DatagramPacket( receivePacket.getData(), receivePacket.getLength(), receivePacket.getPort() receivePacket.getAddress(), receivePack et.getPort() );
que especifica os dados a enviar, o nmero de bytes a enviar, o ); endereo Internet do computador cliente e a porta em que o cliente est esperando receber os pacotes
81 82 83 84 85 86 87 88 89 90
socket.send( sendPacket ); // envia o pacote para o cliente displayMessage( "Packet sent\ sent\n" ); } // fim do mtodo sendPacketToClient // manipula a displayArea na thread de despacho private void displayMessage( final String messageToDisplay ) { SwingUtilities.invokeLater( new Runnable() {
59
Utiliza o mtodo DatagramSocket para enviar o pacote pela rede de send eventos (4 de 4)
Resumo
Server.java
91 public void run() // atualiza displayArea 92 { 93 displayArea.append( displayArea.append( messageToDisplay ); // exibe a mensagem 94 } // fim do mtodo run 95 } // fim da classe interna annima 96 ); // fim da chamada para SwingUtilities.invokeLater 97 } // fim do mtodo displayMessage 98 } // fim da classe Server
1 2 3 4 5 6 7 8 9 10 11 12
// Fig. 24.10: ServerTest.java // Testa Testa a classe Server. Server. import javax.swing.JFrame; public class ServerTest { public static void main( String args[] ) { Server application = new Server(); // cri cria o servidor application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); application.waitForPackets(); // executa o aplicativo do servidor } // fim do main
60
Resumo
ServerTest.java Sada de programa
1 2 3 4 5 6 7 8 9
// Fig. 24.11: Client.java // Cliente Cliente que envia e recebe pacotes para/ para/a partir de um servidor. servidor. import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; java.net.SocketException; import java.n et.SocketException; import java.awt.BorderLayout;
61
Resumo
Client.java
(1 de 5)
import java.awt.event.ActionEvent; 10 import java.awt.event.ActionListener; 11 import javax.swing.JFrame; 12 import javax.swing.JScrollPane; 13 import javax.swing.JTextArea; 14 import javax.swing.JTextField; javax.swing.JTextField; 15 import javax.swing.SwingUtilities; 16 17 public class Client extends JFrame 18 { 19 private JTextField enterField; // para inserir mensagens 20 private JTextArea displayArea; // para exibir mensage ensagen sagens 21 private conectar-se ao servidor priva te DatagramSocket socket; // socket para conectar 22 23 24 25 26 27 // configura a GUI e DatagramSocket public Client() { super( super( "Client" );
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
enterField = new JTextField( "Type message here" ); enterField.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent event ) { try // cria e envia o pacote {
62
Resumo
Client.java
(2 de 5)
// obtm a mensagem no campo de texto Linha 41 String message = event.getActionCommand(); Cria um DatagramPacket e o inicializa com Converte a String displayArea.append( "\nSending packet containing: " +
o array Linhas 44-45 de bytes, o comprimento da string que foi de inserida pelo message + "\n" ); em um array usurio, o endereo IP ao qual o pacote deve ser Linha 47enviado e byte byte data[] = message.getBytes(); // converte convert e em bytes o nmero de porta em que o servidor est esperando Utiliza o mtodo DatagramPacket send para enviar o pacote
// cria cria sendPacket DatagramPacket sendPacket = new DatagramPacket( DatagramPacket( data, data.length, InetAddress.getLocalHost(), 5000 ); socket.send( sendPacket ); // envia o pacote displayArea.append( "Packet sent\ sent\n" ); displayArea.setCaretPosition( displayAre a.setCaretPosition( displayArea.getText().length() ); } // fim do try
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 78 79
catch ( IOException ioException ) { displayMessage( ioException.toString() + "\n" ); ioException.printStackTrace(); } // fim do catch } // fim do actionPerformed } // fim da classe interna annima ); // fim da chamada para addActionListener add( enterField, BorderLayout.NORTH ); displayArea = new JTextArea(); add( new JScrollPane( displayArea ), BorderLayout.CENTER ); setSize( 400, 400, 300 ); // configura o tamanho da janela setVisible( true ); // mostra a janela try // cria pacote cotes cria DatagramSocket para enviar e receber pa cotes { socket = new DatagramSocket(); } // fim do try catch ( SocketException socketException ) { socketException.printStackTrace(); System.exit( 1 ); } // fim do catch } // fim do construtor Client
63
Resumo
Client.java
(3 de 5) Linha 71
// espera que os pacotes cheguem do Server, exibe o contedo do pacote public void waitForPackets() { while ( true ) { try // recebe pacote e exibe contedo { data[] byte d ata[] = new byte[ 100 ]; // configura o pacote DatagramPacket receivePacket = new DatagramPacket( data, data.length ); socket.receive( receivePacket ); // espera o pacote pacote // exibe o contedo do pacote displayMessage( "\ "\nPacket received:" + "\ " \nFrom host: " + receivePacket.getAddress() + "\ " \nHost port: " + receivePacket.getPort() +
64
Resumo
Client.java
Cria um (4 de 5) DatagramPacket Linhas 88-89 para armazenar informaes Linha 95 recebidas Linha 96
Linha 97 Utiliza o mtodo Utiliza o mtodo Linha 98 DatagramPacket Utiliza o mtodo DatagramPacket getPort "\nLength: " + receivePacket.getLength() + getAddress para obter o DatagramPacket para obter o nmero da porta por do "\ "\nContaining:\ nContaining:\n\t" + new String( receivePacket.getData(), receivePacket.getData(), nome de host do computador getLength para obter ohost 0, receivePacket.getLength() ) ); meio da qual computador qual oo pacote foi enviado } // fim do try nmero de bytes dos dados enviou o pacote catch ( IOException IOException exception ) enviado
{ displayMessage( exception.toString() + "\n" ); exception.printStackTrace(); } // fim do catch } // fim do while } // fim do mtodo waitForPackets
Utiliza o mtodo DatagramPacket getData para obter um array de bytes contendo os dados
109 110 111 112 113 114 115 116 117 118 119 120 121 122 }
// manipula a displayArea na thread de despacho de eventos private void displayMessage( final String messageToDisplay ) { SwingUtilities.invokeLater( new Runnable() { public public void run() // atualiza displayArea { displayArea.append( messageToDisplay ); } // fim do mtodo run } // fim da classe inner ); // fim da chamada para SwingUtilities.invokeLater SwingUtilities.invokeLater } // fim do mtodo displayMessage // fim da classe Client
65
Resumo
Client.java
(5 de 5)
1 2 3 4 5 6 7 8 9 10 11 12
// Fig. 24.12: ClientTest.java // Testa Testa a classe Client. import javax.swing.JFrame; public class ClientTest { public static void main( String args[] ) { Client application = new Client(); // cria cria o cliente cliente application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); application.waitForPackets(); // executa o aplicativo cliente cliente } // fim do main // fim da classe ClientTest
66
Resumo
ClientTest.java Sada do programa
13 }
Janela Client depois de enviar pacotes para Server e receber pacotes de volta de Server
67
68
1 2 3 4 5 6 7 8
// Fig. 24.13: TicTacToeServer.java // Essa classe mantm um jogo da velha para dois clientes. clientes. import java.awt.BorderLayout; import java.net.ServerSocket; import java.net.Socket; import java.io.IOException;
69
Resumo
TicTacToeServer .java
import java.util.F java.util.Formatter; ormatter; import java.util.Scanner; 9 import java.util.concurrent.ExecutorService; 10 import java.util.concurrent.Executors; 11 import java.util.concurrent.locks.Lock; 12 import java.util.concurrent.locks.ReentrantLock; 13 import java.util.concurrent.locks.Condition; java.util.concurrent.locks.Condition; 14 import javax.swing.JFrame; 15 import javax.swing.JTextArea; 16 import javax.swing.SwingUtilities; 17
(1 de 12)
18 public class TicTacToeServer extends JFrame 19 { 20 private String[] board = new String[ 9 ]; // tabuleiro do jogojogo-dada-velha 21 private JTextArea outputArea; // para gerar sada das jogadas 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 // varivel de condio para a jogada do outro jogador otherPlayerTurn = gameLock.newCondition(); // varivel de condio para os dois jogadores sendo conectados otherPlayerConnected = gameLock.newCondition(); private Player[] players; // array de Players Players private ServerSocket server; // socket de servidor para conectar com clientes private int currentPlayer; // monitora o jogador com a jogada atual private final static int PLAYER_X = 0; // constante para o primeiro jogador private final static int PLAYER_O = 1; // constante para o segundo jogador private final static String[] String[] MARKS = { "X", "X", "O" }; // array de marca marcas cas private ExecutorService runGame; // executar os jogadores private Lock gameLock; // para bloquear a sincronizao do jogo private Condition otherPlayerConnected; // para esperar outro jogador private Condition otherPlayerTurn; // para esperar a jogada do outro jogador // configura o servidor de tictic-tactac-toe e a GUI que exibe as mensagens public TicTacToeServer() { super( super( "Tic"Tic-TacTac-Toe Server" ); // configura o ttulo da janela // cria ExecutorService com uma thread para cada jogador runGame = Executors.newFixedThreadPool( Executors.newFixedThreadPool( 2 ); gameLock = new ReentrantLock(); // cria um bloqueio para o jogo
70
Resumo
TicTacToeServer .java
(2 de 12)
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
for ( int i = 0; i < 9; i++ ) board[ i ] = new String( "" ); // cria o tabuleiro de jogojogo-dada-velha players = new Player[ 2 ]; // cria array de jogadores PLAYER_X; currentPlayer = PLAYER_X ; // configura o jogador atual como como o primeiro jogador try { server = new ServerSocket( 12345, 12345, 2 ); // configura ServerSocket } // fim do try catch ( IOException ioException ) Cria { ioException.printStackTrace(); ioException.printStackTrace(); System.exit( 1 ); } // fim do catch outputArea = new JTextArea(); // cria cria JTextArea para sada add( outputArea, BorderLayout.CENTER ); connections outputArea.setText( "Server awaiting connection s\n" ); setSize( 300, 300, 300 ); // configura o tamanho da janela setVisible( true ); // mostra a janela } // fim do construtor TicTacToeServer
71
Resumo
TicTacToeServer .java
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
// espera duas conexes para que o jogo possa ser jogado public void execute() { // espera que cada cliente se conecte for ( int i = 0; i < players.length; i++ ) {
72
Resumo
Faz um loop duas vezes, bloqueando na linha 79 toda TicTacToeServer vez enquanto espera a try // espera a conexo, conexo, cria Player, inicia o executvel .java conexo de um cliente { Cria um novo objeto players[ i ] = new Player( server.accept(), i ); Player para gerenciar a (4 de 12) runGame.execute( players[ i ] ); // executa o executvel de jogador conexo como uma thread } // fim de try Executa o Player no pool Linhas 75-87 separada catch ( IOException ioException ) de threads de runGame { Linha 79 ioException.printStackTrace(); Linha 80
System.exit( 1 ); } // fim do catch } // fim do for gameLock.lock(); // bloqueia o jogo para sinalizar sinalizar a thread do jogador X
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
try { players[ PLAYER_X ].setSuspended( false ); // retoma o jogador X otherPlayerConnected.signal(); // acorda a thread do jogador X } // fim do try finally { gameLock.unlock(); // desbloqueia o jogo depois de sinalizar p/ o jogador X } // fim do finally } // fim do mtodo execute // exibe men mensagem sagem na outputArea private void displayMessage( final String messageToDisplay messageToDisplay ) { // exibe uma mensagem da thread de despacho de eventos da execuo SwingUtilities.invokeLater( new Runnable() { public void run() // atualiza outputArea { adiciona outputArea.append( messageToDisplay ); // ad iciona men mensagem sagem } // fim do mtodo run } // fim da classe inner ); // fim da chamada para SwingUtilities.invokeLater } // fim do mtodo displayMessage
73
Resumo
TicTacToeServer .java
(5 de 12)
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
// determina determina se a jogada vlida public boolean validateAndMove( int location, int player ) { // enquanto no for o jogador atual, deve esperar a jogada while ( player != currentPlayer ) { gameLock.lock(); // bloqueia o jogo para que o outro jogador prossiga try { otherPlayerTurn.await(); // espera a jogada do jogador } // fim do try catch ( InterruptedException InterruptedException exception ) { exception.printStackTrace(); } // fim do catch finally { gameLock.unlock(); // desbloqueia o jogo depois de esperar } // fim do finally } // fim do while // se a posio no estiver ocupada, faz a jogada if ( !isOccupied( location ) ) { board[ location ] = MARKS[ currentPlayer ]; // configura uma jogada jogada no tabuleiro currentPlayer = ( currentPlayer + 1 ) % 2; // troca o jogador
74
Resumo
TicTacToeServer .java
(6 de 12)
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
// deixa que novo jogador atual saiba que a jogada ocorreu players[ currentPlayer ].otherPlayerMoved( location ); gameLock.lock(); // bloqueia o jogo p/ sinalizar ao outro jogador a prosseguir try { otherPlayerTurn.signal(); // sinaliza que o outro jogador continue } // fim do try finally { gameLock.unlock(); // desbloqueia jogo depois de sinalizar sinalizar } // fim do finally return true; true; // notifica o jogador que a jogada foi vlida } // fim do if else // jogada no era vlida false; return false ; // notifica o jogador que a jogada jogada foi invlida invlida } // fim do mtodo validateAndMove // determina determina se a posio est ocupada public boolean isOccupied( int location ) { if ( board[ location ].equals( MARKS[ PLAYER_X ] ) || board [ location ].equals( MARKS[ PLAYER_O ] ) ) true; return true ; // posio ocupada else false; return false ; // posio no ocupada } // fim do mtodo isOccupied
75
Resumo
TicTacToeServer .java
(7 de 12)
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
// coloca coloca o cdigo nesse mtodo para determinar se o jogo terminou public boolean isGameOver() { false; return false ; // isso deixado como um exerccio } // fim do mtodo isGameOver // classe interna interna privada Player gerencia cada Player como um executvel private class Player implements Runnable { private Socket connection; // conexo com o cliente private Scanner input; // entrada do cliente private priv ate Formatter output; // sada para o client private int playerNumber; // monitora que que jogador esse private String mark; // marca para esse jogador private boolean suspended = true; true; // se a thread for suspensa suspensa // configura a thread Player public Player( Socket socket, int number ) { playerNumber = number; // armazena o nmero desse jogador mark = MARKS[ playerNumber ]; // especifica a marca do jogador jogador connection = socket; // armazena o socket para o cliente try // obtm obtm fluxos a partir do Socket { input = new Scanner( connection.getInputStream() ); output = new Formatter( connection.getOutputStream() ); } // fim do try
76
Resumo
TicTacToeServer .java
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
catch ( IOException ioException ) { ioException.printStackTrace(); System.exit( 1 ); } // fim do catch } // fim do construtor Player // envia uma uma mensagem de que o outro jogador fez uma jogada public void otherPlayerMoved( int location ) { output.format( "Opponent moved\ moved\n" ); output.format( "%d\ "%d\n", n", location ); // envia posio posio da output.flush(); // esvazia a sada } // fim do mtodo otherPlayerMoved // controla controla a execuo da thread public void run() {
77
Resumo
TicTacToeServer .java
(9 de 12) Formata a sada, Linhas 213-214 notificando o outro jogada Chama o mtodo jogador da jogada Formatter flush Linha 215 para forar a sada para o cliente Linhas 225-226
// envia ao cliente a marca (X ou O), processa as mensagens do cliente try { displayMessage( "Player " + mark + " connected\ connected\n" ); "%s\ n", output.format( "%s \n" , mark ); // envia a marca do jogador output.flush(); sada output.flush( ); // esvazia a sa da
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
// se for o jogador X, espera que o outro jogador chegue if ( playerNumber == PLAYER_X ) { output.format( "%s\ "%s\n%s", n%s", "Player X connected", connected", "Waiting for another another player\ player\n" ); sada output.flush(); // esvazia a sa da gameLock.lock(); // bloqueia o jogo p/ p/ esperar o try {
78
Resumo
Envia uma mensagem indicandoTicTacToeServer que um dos jogadores est conectado e .java segundo jogador esperando um outro jogador (10 de 12) chegar Linhas 231-233 Linhas 254-255
while( while( suspended ) { otherPlayerConnected.await(); // espera o jogador O } // fim do while } // fim do try catch ( InterruptedException InterruptedException exception ) { exception.printStackTrace(); } // fim do catch finally { gameLock.unlock(); // desbloqueia o jogo depois do segundo jogador } // fim do finally // envia uma mensagem de que o outro jogador se conectou output.format( "Other player connected. Your move.\ move.\n" ); output.flush(); outpu t.flush(); // esvazia a sada } // fim do if
Inicia o jogo
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
else { output.format( "Player O connected, please wait\ wait\n" ); output.flush(); // esvazia a sada sada } // fim do else // enquanto o jogo no terminou while ( !isGameOver() ) { int location = 0; // inic inicializa a posio posio da jogada
79
Resumo
TicTacToeServer .java
(11 de 12) Linhas 259-260 L uma Linha jogada 269 Linhas 272 Verifica a jogada Linhas 275-276 Envia uma mensagem indicando que a jogada vlida
if ( input.hasNext() ) location = input.nextInt(); // obtm btm posio posio da jogada // verifica jogada vlida vlida if ( validateAndMove( location, playerNumber ) ) { displayMessage( "\nlocation: " + location ); output.format( move.\ out put.format( "Valid move. \n" ); // notifi notifica o clien cliente sada output.flush(); // esvazia a sa da } // fim do if
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
else // joga foi inv invlida lida { output.format( "Invalid move, try again\ again\n" ); output.flush(); // esvazia a sada } // fim do else } // fim do while } // fim do try finally { try { conexo xo com o cliente connection.close(); // fecha cone } // fim do try catch ( IOException ioException ) { ioException.printStackTrace(); System.exit( 1 ); } // fim do catch } // fim do finally } // fim do mtodo mtodo run // configura se a thread est ou no suspensa public void setSuspended( boolean status ) {
80
Resumo
suspended = status; // configura o valor do suspenso suspenso 303 } // fim do mtodo setSuspended 304 } // fim da classe Player 305 } // fim da classe TicTacToeServer
1 2 3 4 5 6 7 8 9 10 11 12
// Fig. 24.14: TicTacToeServerTest.java // Testa Testa a TicTacToeServer. import javax.swing.JFrame; public class TicTacToeServerTest { public static void main( String args[] ) { TicTacToeServer application = new TicTacToeServer(); TicTacToeServer(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); application.execute(); } // fim do main
81
Resumo
TicTacToeServer Test.java Sada do programa
1 2 3 4 5 6 7 8 9
// Fig. 24.15: TicTacToeClient.java // Classe cliente p/ p/ deixar um usurio jogar o jogojogo-dada-velha c/ c/ um outro usurio por uma rede. rede. import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Graphics; import java.awt.GridLayout; java.awt.event.MouseAdapter; import j ava.awt.event.MouseAdapter; import java.awt.event.MouseEvent;
82
Resumo
TicTacToeClient .java
import java.net.Socket; 10 import java.net.InetAddress; 11 import java.io.IOException; 12 import javax.swing.JFrame; 13 import javax.swing.JPanel; 14 import 15 import 16 import javax.swing.JScrollPane; javax.swing.JScrollPane; javax.swing.JTextArea; javax.swing.JTextField;
(1 de 10)
17 import javax.swing.SwingUtilities; 18 import java.util.Formatter; 19 import java.util.Scanner; 20 import java.util.concurrent.Executors; 21 import java.util.concurren java.util.concurrent.ExecutorService; t.ExecutorService; 22
23 public class TicTacToeClient extends JFrame implements Runnable 24 { 25 private JTextField idField; // campo de texto para exibir a marca do jogador 26 private JTextArea displayArea; // JTextArea para exibir a sada 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 private JPanel boardPanel; // painel para o tabuleiro do jogojogo-dada-velha private JPanel panel2; // painel para conter o tabuleiro private Square board[][]; // tabuleiro do jogojogo-dada-velha private Square currentSquare; // quadrado atual cone servi private Socket connection; // con exo com o serv idor private Scanner input; // entrada a partir do servidor private Formatter output; // sada para o server private String ticTacToeHost; // nome do host para o servidor private private private private String myMark; // marca desse cliente boolean myTurn; // determina de qual cliente a vez final String X_MARK = "X"; "X"; // marc marca para o primeiro cliente cliente "O"; final String O_MARK = "O" ; // mar marca para o segundo segundo cliente cliente
83
Resumo
TicTacToeClient .java
(2 de 10)
// configura a interface com o usurio e o tabuleiro public TicTacToeClient( String String host ) { ticTacToeHost = host; // configura o nome do servidor displayArea = new JTextArea( 4, 30 ); // configura JTextArea displayArea.setEditable( false ); add( new JScrollPane( displayArea ), BorderLayout.SOUTH BorderLayout.SOUTH ); boardPanel = new JPanel(); // configura pai painel para quadrados no tabuleiro boardPanel.setLayout( new GridLayout( 3, 3, 0, 0 ) );
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 77 78
board = new Square[ 3 ][ 3 ]; // cria o tabuleiro // loop over the rows in the board for ( int row = 0; row < board.length; row++ ) { // faz um loop pelas linhas no tabuleiro for ( int column = 0; column < board[ row ].length; column++ ) { // cria cria o quadrado board[ row ][ column ] = new Square( ' ', ', row * 3 + column ); adiciona boardPanel.add( board[ row ][ column ] ); // ad iciona o quadrado } // fim do for interno } // fim da for externo idField = new JTextField(); // configura o campo de texto idField.setEditable( false ); add( idField, BorderLayout.NORTH ); panel2 = new JPanel(); // configura o pai painel para conter boardPanel panel2.add( boardPanel, BorderLayout.CENTER ); // adiciona adiciona o painel do tabuleiro add( panel2, BorderLayout.CENTER ); // adiciona o painel continer continer setSize( 300, 300, 225 ); // configura o tamanho da janela setVisible( true ); // mostra a janela startClient(); } // fim do construtor TicTacToeClient
84
Resumo
TicTacToeClient .java
(3 de 10)
// inicia a thread cliente public void startClient() { try // conectaconecta-se ao servidor, obtm os fluxos e inicia o outputThread Conecta-se { servidor // faz uma conexo com o servidor connection = new Socket( Socket( InetAddress.getByName( ticTacToeHost ), 12345 ); // obtm os fluxos de entrada e sada input = new Scanner( connection.getInputStream() ); output = new Formatter( Formatter( connection.getOutputStream() ); } // fim do try catch ( IOException ioException ) { ioException.printStackTrace(); } // fim do catch // cria cria e inicia thread trabalhadora trabalhadora para esse cliente ExecutorService worker = Executors.newFixedThreadPool( 1 ); executa cliente worker.execute( this ); // execut a o client e } // fim do mtodo startClient // controla controla a thread que permite atualizao contnua da da displayArea displayArea public void run() { myMark = input.nextLine(); // obtm a marca do jogador (X ou O)
85
Resumo
ao
TicTacToeClient .java
(4 de 10) Obtm os fluxos para 85-86 enviarLinhas e receber dados Linhas 89-90 Linha 105
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
SwingUtilities.invokeLater( new Runnable() { public void run() { // exibe a marca do jogador idField.setText( "You are player \"" + myMark + "\ "\"" ); } // fim do mtodo run } // fim da classe interna a annima nnima ); // fim da chamada para SwingUtilities.invokeLater myTurn = ( myMark.equals( X_MARK ) ); // determina determina se a vez do cliente // recebe recebe men mensagen sagens enviadas para o cliente cliente e gera sua sada sada while ( true ) { if ( input.hasNextLine() ) processMessage( input.nextLine() ); } // fim do while } // fim do mtodo run
86
Resumo
TicTacToeClient .java
(5 de 10) Linhas 121-125 Faz um loop Linhas 123-124 continuamente Linhas 132-136
// processa processa men mensagen sagens recebidas recebidas pelo cliente cliente private void processMessage( String message ) { Se a jogada vlida, // ocorreu jogada vlida move." if ( message.equals( "Valid move. " ) ) grava a mensagem e { configura a marca no wait.\ displayMessage( "Valid move, please wait. \n" ); quadrado setMark( currentSquare, myMark ); // configura marca no quadrado } // fim do if
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
else if ( message.equals( "Invalid move, try again" ) ) { displayMessage( message + "\ "\n" ); // exibe jogada invlida invlida myTurn = true; true; // ainda a vez desse cliente } // fim do else if else if ( message.equals( "Opponent moved" ) ) {
87
Resumo
Se a jogada vlida, Se exibe o oponente jogar, a mensagem TicTacToeClient configura a marca no .java quadrado (6 de 10) Linhas 137-141 Linhas 142-153
int location = input.nextInt(); // obtm a posio da jogada input.nextLine(); // pula uma nova linha depois da posio de int location int row = locatio n / 3; // calcula linha coluna int column = location % 3; // calcula colun a
setMark( board[ row ][ column ], ( myMark.equals( X_MARK ) ? O_MARK : X_MARK ) ); // marca a jogada displayMessage( "Opponent moved. Your turn.\ turn.\n" ); true; myTurn = true ; // agora a vez desse cliente } // fim de else if else men sagem displayMessage( message + "\n" ); // exibe a me nsag em } // fim do mtodo processMessage
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
// manipula outputArea na thread de despacho do evento evento private void displayMessage( final String messageToDisplay ) { SwingUtilities.invokeLater( new Runnable() { public void run() { displayArea.append( messageToDisplay ); // atualiza sada } // fim do mtodo run } // fim da classe inner ); // fim da chamada para SwingUtilities.invokeLat SwingUtilities.invokeLater er } // fim do mtodo displayMessage // mtodo utilitrio p/ configurar a marca sobre o tabuleiro na thread de despacho de eventos private void setMark( final Square squareToMark, final String mark ) { SwingUtilities.invokeLater( new Runnable() { public void run() { squareToMark.setMark( mark ); // configura a marca no quadrado } // fim do mtodo ru run n } // fim da classe interna annima ); // fim da chamada para SwingUtilities.invokeLater } // fim do mtodo setMark
88
Resumo
TicTacToeClient .java
(7 de 10)
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
// envia mensagem para o servidor indicando o quadrado clicado public void sendClickedSquare( int location ) { // se for minha vez if ( myTurn ) { output.format( "%d\ "%d\n", n", location ); // envia a posio ao servidor output.flush(); myTurn = false; false; // no minha vez } // fim do if } // fim do mtodo sendClickedSquare // configura quadrado atual public void setCurrentSquare( Square square ) { currentSquare = square; // configura quadrado atual para o argumento argumento } // fim do mtodo setCurrentSquare // classe interna privada para os quadrados no tabuleiro private class Square extends JPanel { private String mark; // marc marca a ser desenhada nesse quadrado private int location; // posio osio do quadrado public Square( String squareMark, int squareLocation ) { mark = squareMark; // configura marca para esse quadrado posio location = squareLocation; // configura posi o desse quadrado
89
Resumo
TicTacToeClient .java
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
addMouseListener( new MouseAdapter() { public void mouseReleased( MouseEvent e ) { Square.this setCurrentSquare( Square. this ); // configura o quadrado atual // envia a posio desse quadrado sendClickedSquare( getSquareLocation() ); } // fim do mtodo mouseReleased } // fim da classe interna annima ); // fim da chamada para addMouseListener } // fim do construtor Square // retorna retorna o tamanho preferido de Square public Dimension getPreferredSize() { 30, return new Dimension( 30 , 30 ); // retorna o tamanho preferido } // fim do mtodo getPreferredSize // retorna o tamanho mnimo de Square public Dimension getMinimumSize() { return getPreferredSize(); // retorna o tamanho preferido getMinimumSize } // fim do mtodo getMini mumSize
90
Resumo
TicTacToeClient .java
(9 de 10)
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
// configura marca para Square public void setMark( String newMark ) { mark = newMark; // configura a marca do quadrado repaint(); // pinta o quadrado novamente } // fim do mtodo mtodo setMark // // retorna a posio de Square public int getSquareLocation() { return location; // retorna a posio do quadrado } // fim do mtodo getSquareLocation // desenha Square public void paintComponent( Graphics g ) { super.paintComponent( super .paintComponent( g );
91
Resumo
TicTacToeClient .java
(10 de 10)
258 259 g.drawRect( 0, 0, 29, 29, 29 ); // desenha desenha o quadrado 260 g.drawString( mark, 11, 11, 20 ); // desenha a marca 261 } // fim do mtodo paintComponent 262 } // fim da classe interna Square 263 } // fim da classe TicTacToeClient
1 2 3 4 5 6 7 8 9 10 11 12
// Fig. 24.16: TicTacToeClientTest.java // Testa Testa a classe TicTacToeClient. TicTacToeClient. import javax.swing.JFrame; public class TicTacToeClientTest { public static void main( String args[] ) { TicTacToeClient application; application; // declara declara o aplicativo cliente cliente // se no houver if ( args.length application = else application = nenhum argumento de linha de comando == 0 ) "127.0.0.1" ); // host local args[ args[ 0 ] ); // usa usa argumentos JFrame.EXIT_ON_CLOSE );
92
Resumo
TicTacToeClient Test.java
13 new TicTacToeClient( 14 15 new TicTacToeClient( 16 17 application.setDefaultCloseOperation( 18 } // fim do main 19 } // fim da classe TicTacToeClientTest
93
94
95
96
97
1 2 3 4 5 6 7 8 9
// Fig. 24.18: DeitelMessengerServer.java // DeitelMessengerServer um servidor de batebate-papo com mltiplas threads, // baseado em socket e em pacotes. pacotes. package com.deitel.messenger.sockets.server; import import import import java.net.ServerSocket; java.net.Socket; java.io.IOException; java.util.concurrent.Executors;
98
Resumo
DeiterMessenger Server.java
10 import java.util.concurrent.ExecutorService; 11 Linha 15 12 import com.deitel.messenger.MessageListener; 13 import static com.deitel.messenger.sockets.SocketMessengerConstants.* com.deitel.messenger.sockets.SocketMessengerConstants.*; ; Implementa a interface Linhas 28-29 14 MessageListener 15 public class DeitelMessengerServer implements MessageListener 16 { 17 private ExecutorService serverExecutor; // executor para o servidor 18 19 bate// inicia o servidor de bate -papo 20 public void startServer() 21 { 22 cr executveis // c ria o executor para execut veis do servidor 23 serverExecutor = Executors.newCachedThreadPool(); 24 25 cria cliente try // cr ia o servidor e gerencia novos client es 26 { Cria um ServerSocket 27 cri // cr ia ServerSocket para conexes entrantes para aceitar conexes de 28 ServerSocket serverSocket = 29 SERVER_PORT, new ServerSocket( SERVER_PORT , 100 ); rede entrantes 30
(1 de 3)
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
System.out.printf( "%s%d%s", "%s%d%s", "Server listening on port ", ", SERVER_PORT, SERVER_PORT , " ..." ); // ouve clientes constantemente while ( true ) { // aceita nova conexo conexo de cliente Socket clientSocket = serverSocket.accept(); // cria cria MessageReceiver para receber receber men mensagen sagens do serverExecutor.execute( new MessageReceiver( this, this, clientSocket ) );
99
Resumo
DeiterMessenger Server.java
Invoca o mtodo accept(2 para de esperar 3) Cria e inicia um novo cliente e aceitar uma nova MessageReceiver conexo de cliente Linha 38 para o cliente
// imprime informaes de conexo conexo System.out.println( "Connection received from: " + clientSocket.getInetAddress() clientSocket.getIn etAddress() ); } // fim do while } // fim do try
Linhas 41-42
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
catch ( IOException ioException ) { ioException.printStackTrace(); } // fim do catch } // fim do mtodo startServer // quando nova mensagem recebida, transmite a mensagem para os clientes clientes public void messageReceived( String from, String message ) { cria // c ria String contendo mensagem inteira String completeMessage = from + MESSAGE_SEPARATOR + message; // cria cria e inicia MulticastSender para transmitir mensagens serverExecutor.execute( new MulticastSender( completeMessage.getBytes() ) );
100
Resumo
DeiterMessenger Server.java
(3 de 3)
Linhas 62-63 Cria e inicia um novo MulticastSender para entregar completeMessage a todos os clientes
1 2 3 4 5 6 7 8 9 10 11
// Fig. 24.19: DeitelMessengerServerTest.java // Testa Testa a classe DeitelMessengerServer. package com.deitel.messenger.sockets.server; public class DeitelMessengerServerTest { public static void main ( String args[] ) { DeitelMessengerServer application = new DeitelMessengerServer(); application.startServer(); // inicia o servidor } // fim do main
101
Resumo
DeitelMessenger ServerTest.java
12 } // fim da classe classe DeitelMessengerServerTest Server listening on Connection Connection received Connection received Connection received port 12345 ... from: /127.0.0.1 from: /127.0.0.1 from: /127.0.0.1
Sada do programa
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 26
// Fig. 24.20: SocketMessengerConstants.java // SocketMessengerConstants define constante constantes para nmeros de porta // e o endereo de multicast em DeitelMessenger package com.deitel.messenger.sockets; public interface SocketMessengerConstants SocketMessengerConstants { // endereo para datagramas de multicast public static final String MULTICAST_ADDRESS = "239.0.0.1"; "239.0.0.1"; // porta porta para ouvir datagramas de multicast public static final int MULTICAST_LISTENING_PORT MULTICAST_LISTENING_PORT = 5555; 5555; // porta porta para enviar datagramas de multicast public static final int MULTICAST_SENDING_PORT = 5554; 5554; // porta conexes es de Socket para DeitelMessengerServer porta para conex public static static final int SERVER_PORT = 12345; 12345; // String que indic indica a desconexo desconexo public static final String DISCONNECT_STRING = "DISCONNECT"; "DISCONNECT"; // String que separa o nome de usurio usurio do corpo da mensagem public static final String MESSAGE_SEPARATOR = ">>>"; ">>>";
102
Resumo
SocketMessenger Constants.java
Endereo para enviar Linhade 9 datagramas multicast 12 Porta queLinha ouve os datagramas de multicast
Linha 15
Porta para enviar datagramas Linha 18 de multicast Porta para conexes de socket ao servidor Linha 24 String Linhaque 27 indica desconexo String que separa o nome do usurio e a mensagem Tamanho mximo da mensagem (em bytes)
Linha 21
// tamanho da mensagem (e (em bytes) 27 public static final int MESSAGE_SIZE = 512; 512; 28 } // fim da interface SocketMessengerConstants
1 2 3 4 5 6 7 8 9
// Fig. 24.21: MessageListener.java // MessageListener uma interface para classes que desejam // receber receber novas mensagens de batebate-papo. papo. package com.deitel.messenger; public interface MessageListener { // recebe recebe uma nova mensagem de batebate-papo public void messageReceived( String from, String message );
103
Resumo
MessageListener .java
O mtodo Linha 9 permite messageReceived que uma classe implementadora receba mensagens de bate-papo
1 2 3 4 5 6 7 8 9
// Fig. 24.22: MessageReceiver.java // MessageReceiver um Runnable que ouve mensagens de um men sagen // cliente particular e entrega me nsage ns para um MessageListener. package com.deitel.messenger.sockets.server; import import import import java.io.BufferedReader; java.io.BufferedReader; java.io.IOException; java.io.InputStreamReader; java.net.Socket;
104
Resumo
MessageReceiver .java
10 import java.net.SocketTimeoutException; 11 import java.util.StringTokenizer; 12 13 import com.deitel.messenger.MessageListener; 14 import static com.deitel.messenger.sockets.SocketMessengerConstants.*; 15 16 public class MessageReceiver implements Runnable 17 { 18 19 20 21 22 23 24 25 26 27 private BufferedReader input; // fluxo de entrada private MessageListener messageListener; // ouviente da mensagem mensagem private boolean keepListening = true; true; // quando falsa falsa, termina executvel // construtor MessageReceiver public MessageReceiver( MessageListener listener, Socket clientSocket ) { ouvinte // configura o ouvi nte ao qual novas mensagens devem ser enviadas messageListener = listener;
(1 de 5)
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
try { // configura o tempo limite para leitura do cliente clientSocket.setSoTimeout( 5000 ); // cinco segundos // cria cria BufferedReader para ler mensagens entrantes input = new BufferedReader( new InputStreamReader( clientSocket.getInputStream() ) ); } // fim do try catch ( IOException ioException ) { ioException.printStackTrace(); } // fim do catch } // fim do construtor MessageReceiver // ouve novas mensagens e as envia para o MessageListener public void run() { String message; // String para mensagens entrantes
105
Resumo
MessageReceiver .java
(2 de 5) Linha 31
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
106
Resumo
L a linha dos
message = input.readLine(); // l a mensagem do cliente MessageReceiver dados no cliente } // fim do try .java catch ( SocketTimeoutException socketTimeoutException ) { (3 de 5) continue; continue ; // continua para a prxima iterao para se manter ouvindo Uma } // fim do catch SocketTimeOutException catch ( IOException ioException ) { ioException.printStackTrace(); break; break; } // fim do catch
// assegura que a mensagem no seja nula if ( message != null ) { Mensagem separada em // divide a mensagem em tokens p/ recuperar o nome do usurio e corpo da mensagem StringTokenizer tokenizer = new StringTokenizer( dois tokens delimitados message, MESSAGE_SEPARATOR );
pelo Message_SEPARATOR
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
107
Resumo
Invoca o mtodo
// envia a mensagem para MessageListener messageReceived da interface messageListener.messageReceived( MessageReceiver MessageListener para entregar a tokenizer.nextToken(), // nome de usurio .java nova mensagem para o tokenizer.nextToken() ); // corpo de mensagem } // fim do if MessageListener registrado (4 de 5) else { 77-79 // se recebeu mensagem de desconexo, pra de ouvir DeterminaLinhas se a mensagem if ( message.equalsIgnoreCase( MESSAGE_SEPARATOR + DISCONNECT_STRING ) ) stopListening(); } // fim do else } // fim do if } // fim do while
try { input.close(); // fecha o BufferedReader (tambm fecha o Socket) } // fim do try catch ( IOException ioException ) { ioException.printStackTrace(); } // fim do catch } // fim do mtodo run // pra de ouvir mensagens entrantes public void stopListening() {
108
Resumo
MessageReceiver .java
(5 de 5)
keepListening = false false; ; } // fim do mtodo stopListening 106 } // fim da classe MessageReceiver MessageReceiver
1 2 3 4 5 6 7 8 9
// Fig. 24.23: MulticastSender.java // MulticastSender transmite uma mensagem de batebate-papo usando um datagrama de multicast. multicast. package com.deitel.messenger.sockets.server; import import import import java.io.IOException; java.net.DatagramPacket; java.net.DatagramSocket; java.net.InetAddress;
109
Resumo
MulticastSender .java
10 import static com.deitel.messenger.sockets.SocketMessengerConstants.*; 11 12 public class MulticastSender implements Runnable 13 { 14 private byte[] messageBytes; // dados de mensagem 15 16 public MulticastSender( byte[] bytes ) 17 { 18 cria messageBytes = bytes; // cr ia a mensagem 19 20 21 22 23 24 25 26 27 28 29 } // fim do construtor MulticastSender
(1 de 2) Linhas 27-28
// entrega a mensagem para o MULTICAST_ADDRESS via um D DatagramSocket atagramSocket public void run() { try // entrega a mensagem { cria // cr ia DatagramSocket para enviar a mensagem Cria um DatagramSocket para DatagramSocket socket = entregar DatagramPackets via new ne w DatagramSocket( MULTICAST_SENDING_PORT );
multicast
30 31 32 33 34 35 36 37 38 39 40 41 42
// utiliza o InetAddress reservado para grupo de multicast InetAddress group = InetAddress.getByName( MULTICAST_ADDRESS ); // cria o DatagramPacket contendo a mensagem DatagramPacket packet packet = new DatagramPacket( messageBytes, messageBytes.length, group, MULTICAST_LISTENING_PORT );
110
Resumo
socket.send( packet ); // envia o pacote para o grupo de multicast Cria o terminando DatagramPacket mtodo run retorna, o socket.close(); // fecha o socket socket } // fim do try catch ( IOException ioException ) {
contm mensagem (2 a de 2) Envia oMulticastSender pacote com o mtodo DatagramSocket send Linha 31 Linhas 34-35 Linha 37 Linha 38
ioException.printStackTrace(); 43 } // fim do catch 44 } // fim do mtodo run 45 } // fim da classe MulticastSend MulticastSender er
111
112
1 2 3 4 5 6 7 8
// Fig. 24.24: MessageManager.java // MessageManeger uma interface para objetos capazes de gerenciar // comunicaes com um servidor de mensagens. mensagens. package com.deitel.messenger;
113
Resumo
public interface MessageManager MessageManager { .java conecta// conecta -se ao servidor de mensagens e roteia as mensagens entrantes Conecta MessageManager ao 9 // para um dado MessageListener Linha 10 DeitelMessengerServer e 10 public void connect( MessageListener listener ); roteia mensagens entrantes para o 11 12 13 14 15 16 17 // desconecta desconecta-se de um servidor de mensagens e pra de rotear // mensagens entrantes para um dado MessageListener public void disconnect( MessageListener listener );
// envia a mensagem para o servidor de mensagens public void sendMessage( String from, String message ); 18 } // fim da interface MessageManager
Linha 14 MessageListener apropriado Desconecta MessageManager do Linha 17 DeitelMessengerServer e pra de entregar mensagens ao MessageListener Envia uma nova mensagem ao DeitelMessengerServer
1 2 3 4 5 6 7 8 9
// Fig. 24.25: SocketMessageManager.java // SocketMessageManager se comunica com um DeitelMessengerServer utilizando // Sockets e MulticastSockets. package com.deitel.messenger.sockets.client; import import import import java.net.InetAddress; java.net.Socket; java.io.IOException; java.util.concurrent.Executors;
114
Resumo
SocketMessage Manager.java
10 import java.util.concurrent.ExecutorService; 11 import java.util.concurrent.ExecutionException; 12 import java.util.concurrent.Future; 13 14 import c com.deitel.messenger.MessageListener; om.deitel.messenger.MessageListener; 15 import com.deitel.messenger.MessageManager; 16 import static com.deitel.messenger.sockets.SocketMessengerConstants.*; 17 18 public class SocketMessageManager implements MessageManager 19 { 20 private Socket clientSocket; // Socket para mensagens enviadas 21 private String serverAddress; // Endereo do DeitelMessengerServer 22 23 24 25 private PacketReceiver receiver; // recebe mensagens de multicast private boolean connected = false; false; // status da conexo private ExecutorService serverExecutor; // executor para o servidor
(1 de 4) Linha 20 Linha 22
Soquete para conectar e enviar mensagens ao DeitelMessengerServer Runnable ouve as mensagens entrantes
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 53
public SocketMessageManager( String address ) { serverAddress = address; // armazena o endereo de servidor serverExecutor = Executors.newCachedThreadPool(); } // fim do construtor SocketMessageManager // conectaconecta-se ao servidor e envia mensagens para um dado MessageListener public void connect( MessageListener listener ) { if ( connected ) return; return; // se j conectado, retorna imediatamente try // abre a conexo de Socket ao DeitelMessengerServer com { clientSocket = new Socket( InetAddress.getByName( serverAddress ), SERVER_PORT );
115
Resumo
SocketMessage Manager.java
(2 de 4) Linhas 40-41 Socket Cria Socket para se comunicar Linha com o 44 DeitelMessengerServer Linha 45
Cria um novo packetReceiver, // cria um executvel para receber as mensagens entrantes que ouve as mensagens de multicast receiver = new PacketReceiver( listener ); Runnable serverExecutor.execute( receiver ); // executa o executvel entrantesExecuta no servidor true; connected = true ; // atualiza o flag conectado } // fim do try IOException catch ( IOE xception ioException ) {
ioException.printStackTrace(); } // fim do catch } // fim do mtodo connect
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 79 80 81 82
// desconectadesconecta-se do servidor e remove o registro de um dado MessageListener public void disconnect( MessageListener listener ) { Cria um novo MessageSender if ( !connected ) return; return; // se no conectado, retorna imediatamente
116
DISCONNECT_STRING ao servidor
Invoca get para que a try // pra o o mtodo ouvinteFuture e desconecta-se doesperar servidor desconecta mensagem utilizando o mtodo submit de Manager.java { mensagem de desconexo seja entregue e que ExecutorService // notifica o servidor de que o cliente est se desconectando Runnable termine
Runnable disconnecter = new MessageSender( clientSocket, "", "", DISCONNECT_STRING DISC ONNECT_STRING ); Future disconnecting = serverExecutor.submit( disconnecter ); disconnecting.get(); // espera que a mensagem de desconexo seja enviada receiver.stopListening(); receiver.stopListening (); // pra o receptor clientSocket.close(); // fecha o Socket sainte } // fim do try catch ( ExecutionException exception ) { exception.printStackTrace(); } // fim do catch catch ( InterruptedException exception ) { exception.printStackTrace(); } // fim do catch catch ( IOException ioException ) { ioException.printStackTrace(); } // fim do catch
83 84 85 86 87 88 89 90 91 92 93 94 95
connected = false; false; // atualiza o flag conectado } // fim do mtodo disconnect // envia mensagem ao servidor public void sendMessage( String from, String message ) { if ( !connected ) return; return; // se no conectado, retorna imediatamente // cria e inicia um novo MessageSender para entregar a mensagem serverExecutor.execute( new MessageSender( clientSocket, from, message) ); } // fim do mtodo sendMessage
117
Resumo
SocketMessage Manager.java
(4 de 4) Cria e inicia um novo Linhas 93-94para MessageSender entregar a nova mensagem em uma thread separada da execuo
1 2 3 4 5 6 7 8 9
// Fig. 24.26: MessageSender.java // Envia uma mensagem para o servidor de batebate-papo em um executvel separado. separado. package com.deitel.messenger.sockets.client; import java.io.IOException; import java.util.Formatter; import java.net.Socket; java.net.Socket; import static com.deitel.messenger.sockets.SocketMessengerConstants.*;
118
Resumo
MessageSender.java
(1 de 2)
10 11 public class MessageSender implements Runnable 12 { 13 private Socket clientSocket; // Socket pelo qual enviar a mensagem 14 private String messageToSend; messageToSend; // mensagem a enviar 15 16 public MessageSender( Socket socket, String userName, String message ) 17 { 18 clientSocket = socket; // armazena o socket para o cliente 19 20 21 22 23 // cria uma mensagem a ser enviada messageToSend = userName + MESSAGE_SEPARATOR + message; } // fim do construtor MessageSender
24 25 26 27 28 29 30 31 32 33 34 35 36
// envia a mensagem e finaliza public void run() { try // envia a mensagem e esvazia PrintWriter {
119
Resumo
Cria um novo Formatter para o OutputStream do Formatter output = MessageSender.java Invoca o mtodo new Formatter( clientSocket.getOutputStream() clientSocket.getOutputStream() );Invoca o mtodo clientSocket Formatter format output.format( "%s\ "%s\n", n", messageToSend ); // envia a mensagem Formatter flush (2 deformatar 2) para a output.flush(); // esvazia sada para assegurar que a } // fim do try mensagem Linhas 29-30 mensagem seja enviada catch ( IOException ioException ) imediatamente { Linha 31 ioException.printStackTrace(); Linha 32
1 2 3 4 5 6 7 8
// Fig. 24.27: PacketReceiver.java // PacketReceiver ouve DatagramPackets contendo // mensagens de um DeitelMessengerServer. DeitelMessengerServer. package com.deitel.messenger.sockets.client;
120
Resumo
PacketReceiver .java
import java.io.IOException; import java.net.InetAddress; import java.net.MulticastSocket; 9 import java.net.DatagramPacket; 10 import java.net.SocketTimeoutException; 11 import java.util.StringTokenizer; 12 13 import com.deitel.messenger.MessageListener; 14 import static com.deitel.messenger.sockets.SocketMessengerConstants.*; com.deitel.messenger.sockets.SocketMessengerConstants.*; 15 16 public class PacketReceiver implements Runnable 17 { 18 19 20 21 22 23 24 25 26 private private private private MessageListener messageListener; // recebe MulticastSocket multicastSocket; // recebe InetAddress multicastGroup; // InetAddress true; boolean keepListening = true ; // termina o as mensagens as mensagens de broadcast do grupo de multicast PacketReceiver
(1 de 4)
public PacketReceiver( MessageListener listener ) { messageListener messageListener = listener; // configura configura MessageListener
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 53 54 55 56
try // conecta o MulticastSocket ao endereo de multicast e porta { MulticastSocket ouve // cria cria novo MulticastSocket multicastSocket = new MulticastSocket( mensagens de bate-papo entrantes
121
Resumo
MULTICAST_LISTENING_PORT );
// usa usa InetAddress para obter grupo de multicast multicastGroup = InetAddress.getByName( MULTICAST_ADDRESS );
// associaassocia-se ao grupo de multicast para receber mensagens Objeto multicastSocket.joinGroup( multicastGroup ); // configura um tempo limite de 5 segundos ao multicastSocket.setSoTimeout( 5000 ); } // fim do try catch ( IOException ioException ) { ioException.printStackTrace(); } // fim do catch } // fim do construtor PacketReceiver // ouve mensagens do grupo de multicast public void run() { // ouve mensagens at ser parado while ( keepListening ) { cria // cr ia buffer para men mensagem sagem entrante byte[] buffer = new byte[ MESSAGE_SIZE ];
(2 de 4) InetAddress para o qual Linhas 30-31 o DeitelMessengerServer Registra o faz o multicast das mensagens de esperar novos pacotes MulticastSocket para Linha 34 bate-papo receber mensagens enviadas a Invoca o mtodo MulticastSocket MULTICAST_ADDRESS Linha 37 setSoTimeout para especificar que, se nenhum dado for recebido em 5000 Linha 40 milissegundos, o MulticastSocket deve emitir uma Linha 55 InterruptedIOException
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
// cria DatagramPacket para mensagem entrante DatagramPacket packet = new DatagramPacket( buffer, MESSAGE_SIZE ); try // recebe um novo DatagramPacket (chamada (chamada bloqueadora) { multicastSocket.receive( packet ); } // fim do try catch ( SocketTimeoutException socketTimeoutException ) {
122
Resumo
continue; continue; // continua para a prxima iterao para se manter ouvindo } // fim do catch catch ( IOException ioException ) { ioException.printStackTrace(); break; break ; } // fim do catch // coloca os dados da mensagem em uma String String message = new String( packet.getData() ); message = message.trim(); // apara o espao em branco na mensagem
Invoca o mtodo trim da classe String para // divide a mensagem em tokens p/ recuperar o nome do usurio e corpo da mensagem StringTokenizer tokenizer = new StringTokenizer( remover espaos em Cria um StringTokenizer message, MESSAGE_SEPARATOR ); branco extras do final da para separar o corpo da mensagem mensagem do nome do usurio que enviou a mensagem
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
// ignora as mensagens que no contm um nome de usurio // e um corpo de mensagem if ( tokenizer.countTokens() == 2 ) { // envia a mensagem para MessageListener messageListener.messageReceived( tokenizer.nextToken(), // nome de tokenizer.nextToken() ); // corpo } // fim do if } // fim do while try { multicastSocket.leaveGroup( multicastGroup ); // deixa o multicastSocket.close(); // fecha MulticastSocket } // fim do try catch ( IOException ioException ) { ioException.printStackTrace(); } // fim do catch } // fim do mtodo run // pra de ouvir novas men mensagen sagens public void stopListening() { false; keepListening = false ; } // fim do mtodo stopListening
123
Resumo
Depois de analisar sintaticamente a mensagem, PacketReceiver entrega a mensagem para usurio MessageListener do .java PacketReceiver de mensagem Invoca ode mtodo (4 4) MulicastSocket Linhas 89-91 leaveGroup para parar o recebimento de mensagens do Linha 97 grupo grupo endereo de o multicast Invoca mtodo MulticastSocket close Linha 98 para fechar o MulticastSocket
1 2 3 4 5 6 7 8
// Fig. 24.28: ClientGUI.java // A ClientGUI fornece uma interface com o usurio para enviar e receber // mensagens para e do DeitelMessengerServer. DeitelMessengerServer. package com.deitel.messenger;
124
Resumo
ClientGUI.java
import java.awt.BorderLayout; import java.awt.event.ActionEvent; java.awt.event.ActionEvent; import java.awt.event.ActionListener; 9 import java.awt.event.WindowAdapter; 10 import java.awt.event.WindowEvent; 11 import javax.swing.Box; 12 import javax.swing.BoxLayout; 13 import javax.swing.Icon; 14 import javax.swing.Im javax.swing.ImageIcon; ageIcon; 15 import javax.swing.JButton; 16 import javax.swing.JFrame; 17 import javax.swing.JLabel; 18 19 20 21 22 23 24 import import import import import import import javax.swing.JMenu; javax.swing.JMenuBar; javax.swing.JMenuItem; javax.swing.JOptionPane; javax.swing.JPanel; j avax.swing.JPanel; javax.swing.JScrollPane; javax.swing.JTextArea;
(1 de 10)
28 public class ClientGUI extends JFrame 125 29 { 30 private JMenu serverMenu; // para conectar/desconectar o servidor 31 private JTextArea messageArea; // exibe as mensagens 32 private JTextArea inputArea; // insere men mensage ensagens sagens 33 private private JButton connectButton; // boto para conectar ClientGUI.java 34 private JMenuItem connectMenuItem; // item de menu para conectar 35 private JButton disconnectButton; // boto para desconectar (2 de 10) 36 private JMenuItem disconnectMenuItem; // item de menu para para desconectar 37 private JButton sendButton; // envia mensagens Linha 40 38 private JLabel statusBar; // rtulo para o status da conexo 39 private String userName; // userName para adicionar a mensagens enviadas 40 private MessageManager messageManager; messageManager; // comunicacomunica-se com o servidor Linha 41 41 private MessageListener messageListener; // recebe mensagens entrantes MessageListener 42 O MessageManager 43 // construtor ClientGUI recebe mensagens entrantestrata a comunicao com o servidor de 44 public ClientGUI( MessageManager manager ) de MessageManager bate-papo 45 { 46 super( super( "Deitel "Deitel Messenger" ); 47 48 messageManager = manager; // configura MessageManager 49
Resumo
50 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
// cria MyMessageListener para receber mensagens messageListener = new MyMessageListener(); serverMenu = new JMenu serverMenu.setMnemonic( serverMenu. setMnemonic(
126
JMenuBar menuBar = new menuBar.add( serverMenu ); // adiciona o menu de servidor barra de menus adiciona diciona JMenuBar ao aplicati setJMenuBar( menuBar ); // a aplicativo cativo // cria cria ImageIcon para botes de conexo conexo Icon connectIcon = new ImageIcon( lus().getResource( "images/Connect.gif" ) ); // cria cria connectButton e connectMenuItem connectButton connectB utton = new JButton( "Connect", "Connect", connectIcon ); connectMenuItem = new JMenuItem( "Connect", "Connect", connectIcon ); connectMenuItem.setMnemonic( 'C' ); // cria cria ConnectListener botes de conexo ActionListener ActionListe ner connectListener = new ConnectListener(); connectButton.addActionListener( connectListener ); connectMenuItem.addActionListener( connectListener ); // cria cria ImageIcon para botes de desconexo Icon disconnectIcon disconnectIcon = new ImageIcon( getClass().getResource( "images/Disconnect.gif" ) );
Cria uma instncia de ( "Server" ); // cria cria o JMenu do servidor MyMessageListener, que implementa a interface 'S' ); // configura configura o mnemnico p/ o menu de servidor JMenuBar(); // croa croa o JMenuBar MessageListener ClientGUI.java (3 de 10) Linha 51
Resumo
// cria cria disconnectButton e disconnectMenuItem disconnectButton = new JButton( "Disconnect", "Disconnect", disconnectIcon ); "Disconnect", disconnectMenuItem = new JMenuItem( "Disconnect" , disconnectIcon ); disconnectMenuItem.setMnemonic( 'D' ); // desativa o boto de desconexo e o item de menu disconnectButton.setEnabled( false ); disconnectMenuItem.setEnabled( false ); // cria DisconnectListener para botes de desconexo ActionListener disconnectListener = new DisconnectListener(); disconnectButton.addActionListener( disconnectListener ); disconnectMenuItem.addActionListener( disconnectListener ); // adiciona os JMenuItems JMenuItems de conexo e desconexo ao fileMenu serverMenu.add( connectMenuItem ); serverMenu.add( disconnectMenuItem ); // adiciona JButtons de conexo e conexo ao buttonPanel JPanel buttonPanel = new new JPanel(); buttonPanel.add( connectButton ); buttonPanel.add( disconnectButton ); messageArea = new JTextArea(); // exibe men mensag ensagen sagens ens messageArea.setEditable( false ); // desativa desativa edio edio messageArea. essageArea.setWrapStyleWord( m essageArea. setWrapStyleWord( true ); // configura o estilo de quebra de linha messageArea.setLineWrap( true ); // ativa a quebra de linha
127
Resumo
ClientGUI.java
(4 de 10)
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
// coloca a messageArea no JScrollPane para permitir rolagem JPanel messagePanel = new JPanel(); messagePanel.setLayout( new BorderLayout( 10, 10, 10 ) ); messagePanel.add( new JScrollPane( messageArea ), BorderLayout.CENTER ); inputArea = new JTextArea( 4, 20 ); // para inserir novas mensagens inputArea.setWrapStyleWord( inputArea.setWrapStyleWord ( true ); // configura o estilo de quebra de linha inputArea.setLineWrap( true ); // ativa a quebra de linha inputArea.setEditable( false ); // desativa a edio // cria Icon para sendButton Icon sendIcon = new ImageIcon( getClass().getResource( "images/Send.gif" ) );
128
Resumo
ClientGUI.java
sendButton = new JButton( "Send", "Send", sendIcon ); // cria o boto de enviar sendButton.setEnabled( false ); // desativa o boto de enviar sendButton.addActionListener( new ActionListener() { // envia uma nova mensagem quando usurio ativa o sendButton public void actionPerformed( ActionEvent event ) Envia o nome do usurio e { messageManager.sendMessage( userName, inputArea a inputArea.getText() ); // envia mensagem inputArea.setText( "" ); // limpa inputArea } // fim do mtodo actionPerformed } // fim da classe interna annima ); // fim da chamada para addActionListener
o texto da
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
Box box = new Box( BoxLayout.X_AXIS ); // cria uma nova caixa para layout box.add( new JScrollPane( inputArea ) ); // adiciona a rea de entrada caixa box.add( sendButton ); // adiciona o boto Enviar caixa messagePanel.add( box, BorderLayout.SOUTH ); // adiciona a caixa ao painel // cria um JLabel para statusBar com uma borda reentrante statusBar = new JLabel( "Not Connected" ); statusBar.setBorder( new BevelBorder( BevelBorder( BevelBorder.LOWERED ) ); add( buttonPanel, BorderLayout.NORTH ); // adiciona adiciona painel de boto add( messagePanel, BorderLayout.CENTER ); // adiciona painel de mensagem mensagem add( statusBar, BorderLayout.SOUTH ); // adiciona adiciona barra de status // adiciona WindowListener para desconectar quando o usurio sair addWindowListener ( new WindowAdapter () { // desconectadesconecta-se do servidor e encerra encerra o aplicativo public void windowClosing ( WindowEvent event ) { messageManager.disconnect( messageListener ); System.exit( 0 ); } // fim do mtodo windowClosing windowClosing } // fim da classe interna annima ); // fim da chamada para addWindowListener } // fim do construtor ClientGUI
129
Resumo
ClientGUI.java
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
// ConnectListener ouve solicitaes do usurio para conectar ao servidor private class ConnectListener implements ActionListener { conecta// conecta -se ao servidor e ativa/desativa componentes GUI public void actionPerformed( actionPerformed( ActionEvent event ) { conecta// conecta -se ao servidor e roteia mensagens para messageListener Quando o usurio messageManager.connect( messageListener ); // solicita o userName userName = JOptionPane.showInputDialog( ClientGUI.this ClientGUI.this, this, "Enter user name:" ); messageArea.setText( "" ); // limpa a messageArea connectButton.setEnabled( false ); // desativa conectar connectMenuItem.setEnabled( false ); // desativa conectar disconnectButton.setEnabled( true ); // ativa de desconectar sconectar disconnectMenuItem.setEnabled( true ); // ativa desconectar sendButton.setEnabled( s endButton.setEnabled( true ); // ativa o boto Enviar inputArea.setEditable( true ); // ativa a edio para a rea de entrada inputArea.requestFocus(); // configura foco para a rea de entrada statusBar.setText( "Connected: " + userName ); // configura texto texto } // fim do mtodo actionPerformed } // fim da classe interna ConnectListener
130
Resumo
ClientGUI.java
acessa o menu Connect, conecta-se ao servidor bate-papo (7 de de 10) Linha 169 Solicita ao usurio um nome de usurio Linhas 172-173
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
// DisconnectListener ouve solicitaes do usurio para desconectardesconectar-se // de DeitelMessengerServer private class DisconnectListener implements ActionListener { // desconectadesconecta-se do servidor e ativa/desativa componentes componentes GUI public void actionPerformed( ActionEvent event ) { desconecta// desconecta -se do servidor e pra de rotear mensagens messageManager.disconnect( messageListener );
131
Resumo
ClientGUI.java
(8 de 10)
sendButton.setEnabled( sendButton.setEnabled( false ); // desativa o boto de enviar Linha 195 disconnectButton.setEnabled( false ); // desativa desconectar desconectar disconnectMenuItem.setEnabled( false ); // desativa Invoca o mtodo MessageManager desativa edio inputArea.setEditable( false ); // de sativa edi o disconnect para se desconectar do connectButton.setEnabled( true ); // ativa a conexo connectMenuItem.setEnabled( true ); // ativa a conexo statusBar.setText( "Not Connected" ); // configura a barra de status } // fim do mtodo actionPerformed } // fim da classe interna DisconnectListener
servidor de bate-papo
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
// MyMessageListener ouve novas mensagens do MessageManager e // exibe as mensagens na messageArea utilizando o MessageDisplayer. MessageDisplayer. private class MyMessageListener implements MessageListener { // quando recebida, recebida, exibe novas mensagens na messageArea public void messageReceived( String from, String message ) { // acrescenta a mensagem utilizando o MessageDisplayer SwingUtilities.invokeLater( new MessageDisplayer( from, message ) ); } // fim do mtodo messageReceived classe } // fim da cla sse interna MyMessageListener
132
Resumo
ClientGUI.java
(9 de 10) Exibe a mensagem quando Linhas 211-216 MessageListener detecta que a mensagem foi recebida
// Exibe nova mensagem acrescentando a mensagem JTextArea. Deve // ser executado somente na thread Event; modifica componente Swing ativo private class MessageDisplayer implements Runnable Runnable { private String fromUser; // usurio do qual a mensagem veio private String messageBody; // corpo da mensagem
226 227 228 229 230 231 232 233 234 235 236 237 238
// construtor MessageDisplayer public MessageDisplayer( String from, String body ) { fromUser = from; // armazena o usurio que origina a mensagem messageBody = body; // armazena o corpo da mensagem } // fim do construtor MessageDisplayer // exibe nova mensagem na messageArea public void run() { // acrescenta nova mensagem
133
Resumo
ClientGUI.java
(10 de 10) Linha 237 Acrescenta o nome de usurio, > e messageBody messageArea
messageArea.append( "\n" + fromUser + "> " + messageBody ); } // fim do mtodo run 239 } // fim da classe interna MessageDisplayer 240 } // fim da classe ClientGUI
1 2 3 4 5 6 7 8
// Fig. 24.29: DeitelMessenger.java // DeitelMessenger um aplicativo de batebate-papo que utiliza um ClientGUI DeitelMessengerServer. . // e um SocketMessageManager para se comunicar com o DeitelMessengerServer package com.deitel.messenger.sockets.client; import import com.deitel.messenger.MessageManager; import com.deitel.messenger.ClientGUI;
134
Resumo
DeitelMessenger .java
9 public class DeitelMessenger 10 { 11 public static void main( String args[] ) 12 { 13 MessageManager messageManager; // declara MessageManager MessageManager 14 15 if ( args.length == 0 ) 16 conecta// conecta -se ao host local 17 messageManager = new SocketMessageManager( "localhost" ); 18 else 19 conecta// conecta -se utilizando o argumento de linha de comando 20 messageManager = new SocketMessageManager( args[ 0 ] ); 21 22 // cria a GUI para SocketMessageManager 23 ClientGUI clientGUI = new ClientGUI( messageManager ); 24 300, tamanho clientGUI.setSize( 300 , 400 ); // configura o t amanho da janela 25 clientGUI.setResizable( false ); // desativa o redimensionamento 26 clientGUI.setVisible( true ); // mostra a janela 27 } // fim do main 28 } // fim da classe DeitelMessenger
(1 de 3) Linha 17 Linha 20 Linha 23 Cria um cliente para se conectar ao host local Conecta-se a um host fornecido pelo usurio Cria uma ClientGUI para o MessageManager
135
Resumo
DeitelMessenger .java
(2 de 3)
136
Resumo
DeitelMessenger .java
(3 de 3)
java com.deitel.messenger.sockets.client.DeitelMessenger
137
Que equivalente a:
java com.deitel.messenger.sockets.client.DeitelMessenger localhost
ou
java com.deitel.messenger.sockets.client.DeitelMessenger 127.0.0.1