Você está na página 1de 137

1

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.

2005 by Pearson Education do Brasil

24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9

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.10 Estudo de caso: Servidor e cliente DeitelMessenger

24.11 Concluso

2005 by Pearson Education do Brasil

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).

Comunicaes baseadas em pacotes:


Transmitem pacotes individuais de informaes. Utilizam UDP (User Datagram Protocol) que um servio sem conexo.

2005 by Pearson Education do Brasil

24.1 Introduo (Continuao)


Relacionamento cliente-servidor:
O cliente solicita alguma ao a ser realizada. O servidor realiza a ao e responde ao cliente. Modelo de solicitao-resposta:
Implementao comum: Navegadores Web e servidores Web.

2005 by Pearson Education do Brasil

Dica de desempenho 24.1


Servios sem conexo geralmente oferecem desempenho maior, mas menos confiabilidade do que os servios orientados a conexo.

2005 by Pearson Education do Brasil

Dica de portabilidade 24.1


O TCP, o UDP e os protocolos relacionados permitem que uma grande variedade de sistemas de computadores heterogneos (isto , sistemas de computadores com diferentes processadores e diferentes sistemas operacionais) se intercomuniquem.

2005 by Pearson Education do Brasil

24.2 Manipulando URLs


Hypertext Transfer Protocol (HTTP):
Utiliza URIs (Uniform Resource Identifier) para identificar os dados.
URLs (Uniform Resource Locators): URIs que especificam as localizaes dos documentos. Referenciam arquivos, diretrios e objetos complexos.

Documento HTML SiteSelector.html (Figura 24.1):


Elemento applet. Tag param:
Atributo name. Atributo value.
2005 by Pearson Education do Brasil

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

| O documento HTML para carregar a applet


2005 by Pearson Education do Brasil

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

Importa classes no pacote java.net

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

Importa a interface AppletContext do pacote (1 de 5) java.net Linhas 3-4 Linha 8

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();

2005 by Pearson Education do Brasil

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

add( new JScrollPane( siteChooser ), BorderLayout.CENTER BorderLayout.CENTER ); } // fim do mtodo init

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

86 87 88 89

counter++; title = getParameter( "title" + counter ); // obtm o prximo ttulo do site } // fim do while } // fim do mtodo getSitesFromHTMLParameters

13

Resumo

90 } // fim da classe classe SiteSelector

Utiliza o mtodo Applet SiteSelector.java getParameter para obter o ttulo do (4 de 5) prximo site Linha 87 Sada do programa

2005 by Pearson Education do Brasil

14

Resumo
SiteSelector.java

(5 de 5) Sada do programa

2005 by Pearson Education do Brasil

24.2 Manipulando URLs (Continuao)


Frames HTML:
Especifica o frame-alvo no mtodo showDocument:
_blank _self _top

15

2005 by Pearson Education do Brasil

16

Dica de preveno de erro 24.1


A applet na Figura 24.2 deve ser executada a partir de um navegador Web, como o Mozilla ou o Microsoft Internet Explorer, para ver os resultados da exibio de uma outra pgina da Web. O appletviewer s capaz de executar applets ele ignora todas as outras tags HTML. Se os sites Web no programa contiverem applets Java, somente essas applets aparecero no appletviewer quando o usurio selecionar um site Web. Cada applet executaria em uma janela appletviewer separada.

2005 by Pearson Education do Brasil

24.3 Lendo um arquivo em um servidor Web


Componente GUI Swing JEditorPane:
Renderiza tanto texto simples como texto formatado em HTML. Atua como um navegador Web simples.
Recupera arquivos de um servidor Web em um dado URI. HyperlinkEvents: Ocorrem quando o usurio clica em um hyperlink. Trs tipos de eventos: HyperlinkEvent.EventType.ACTIVATED HyperlinkEvent.EventType.ENTERED HyperlinkEvent.EventType.EXITED

17

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

12 } // fim da classe classe ReadServerFileTest

2005 by Pearson Education do Brasil

22

Resumo
ReadServerFileTest .java

(2 de 2) Sada do programa

2005 by Pearson Education do Brasil

23

Observao sobre aparncia e comportamento 24.1


Um JEditorPane gera HyperlinkEvents somente se eles forem no-editveis.

2005 by Pearson Education do Brasil

24.4 Estabelecendo um servidor simples utilizando sockets de fluxo


Cinco passos para criar um servidor simples em Java:
Passo 1: Criar o objeto ServerSocket:
ServerSocket server = new ServerSocket( ServerSocket( nmeroDaPorta, comprimentoDaFila ); Registra uma porta disponvel. Especifica um nmero mximo de clientes. Ponto de handshake. Vincula o servidor a uma porta. Somente um cliente pode ser vinculado a uma porta especfica.

24

2005 by Pearson Education do Brasil

25

Observao de engenharia de software 24.1


Os nmeros de porta podem estar entre 0 e 65.535. A maioria dos sistemas operacionais reserva nmeros de porta abaixo de 1.024 para servios de sistema (por exemplo, correio eletrnico e servidores da World Wide Web). Geralmente, essas portas no devem ser especificadas como portas de conexo nos programas de usurio. De fato, alguns sistemas operacionais requerem privilgios especiais de acesso para que possam ser vinculados a nmeros de porta abaixo de 1.024.

2005 by Pearson Education do Brasil

24.4 Estabelecendo um servidor simples utilizando sockets de fluxo (Continuao)


Cinco passos para criar um servidor simples em Java:
Passo 2: O servidor ouve a conexo cliente:
O servidor bloqueia at o cliente se conectar. Socket connection = server.accept();

26

Passo 3: Enviar e receber dados:


OutputStream para enviar, e InputStream para receber dados: O mtodo getOutputStream retorna OutputStream do Socket. O mtodo getInputstreams retorna InputStream de Socket.

2005 by Pearson Education do Brasil

24.4 Estabelecendo um servidor simples utilizando sockets de fluxo (Continuao)


Cinco passos para criar um servidor simples em Java:
Passo 4: Fase de processamento:
O servidor e o cliente se comunicam via fluxos.

27

Passo 5: Fechar fluxos e conexes.


Mtodo close.

2005 by Pearson Education do Brasil

28

Observao de engenharia de software 24.2


Com sockets, a E/S de rede aparece para programas Java como sendo similar E/S de arquivo seqencial. Os sockets ocultam muito da complexidade de programao de rede do programador.

2005 by Pearson Education do Brasil

29

Observao de engenharia de software 24.3


Com o multithreading do Java, podemos criar servidores com mltiplas threads que podem gerenciar vrias conexes simultneas com vrios clientes. Essa arquitetura de servidor com mltiplos threads precisamente a que utilizada nos servidores de rede populares.

2005 by Pearson Education do Brasil

30

Observao de engenharia de software 24.4


Um servidor com mltiplas threads pode receber o Socket retornado por uma a uma das chamadas a accept e criar uma nova thread que gerencia a E/S de rede por meio desse Socket. Alternativamente, um servidor com mltiplas threads pode manter um pool de threads (um conjunto de threads existentes) pronto para gerenciar a E/S de rede por meio dos novos Sockets medida que so criados. Consulte o Captulo 23 para informaes adicionais sobre multithreading.
2005 by Pearson Education do Brasil

31

Dica de desempenho 24.2


Em sistemas de alto desempenho em que a memria abundante, um servidor multiencadeado pode ser implementado para criar um pool de threads que pode ser atribudo rapidamente para tratar E/S de rede atravs de cada novo Socket quando ele criado. Portanto, quando o servidor recebe uma conexo, ele no precisa incorrer no overhead da criao de thread. Quando a conexo fechada, a thread retornada ao pool para reutilizao.

2005 by Pearson Education do Brasil

24.5 Estabelecendo um cliente simples utilizando sockets de fluxo


Quatro passos para criar um cliente simples em Java:
Passo 1: Criar um Socket para conexo ao servidor: Socket connection = new Socket ( endereoDoServidor, porta ); Passo 2: Obter InputStream e Outputstream de Socket. Passo 3: Processar informaes comunicadas. Passo 4: Fechar fluxos e conexo.

32

2005 by Pearson Education do Brasil

24.6 Interao cliente/servidor com conexes de socket de fluxo


Aplicativo de bate-papo cliente/servidor simples:
Utiliza soquetes de fluxo. O servidor espera uma tentativa de conexo do cliente. O cliente conecta-se ao servidor:
Envia e receber mensagens.

33

O cliente ou o servidor fecha a conexo. O servidor espera que o prximo cliente se conecte.

2005 by Pearson Education do Brasil

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

que se conecta ao cliente

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104

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

Obtm OutputStream de Socket e

2005 by Pearson Education do Brasil

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 {

Obtm InputStream de Socket e utilizaServer.java o para inicializar ObjectInputStream

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 {

Linha 106 Linha 124

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

Utiliza o mtodo ObjectInputStream readObject para ler uma String do cliente

2005 by Pearson Education do Brasil

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

O mtodo closeConnection fecha fluxos e sockets (6 de 8)

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

Utiliza o mtodo ObjectOutputStream writeObject para enviar uma String ao cliente

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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)

195 } // fim da classe classe Server

2005 by Pearson Education do Brasil

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

13 } // fim da classe classe ServerTest

2005 by Pearson Education do Brasil

43

Erro comum de programao 24.1


Especificar uma porta que j est em utilizao ou especificar um nmero de porta invlido ao criar um ServerSocket resulta em uma BindException.

2005 by Pearson Education do Brasil

44

Observao de engenharia de software 24.5


Ao utilizar um ObjectOutputStream e um ObjectInputStream para enviar e receber objetos em uma conexo de rede, sempre crie o ObjectOutputStream primeiro e esvazie (flush) o fluxo de modo que o ObjectInputStream do cliente possa se preparar para receber os dados. Isso s necessrio para aplicativos de rede que se comunicam utilizando ObjectOutputStream e ObjectInputStream.

2005 by Pearson Education do Brasil

45

Dica de desempenho 24.3


Os componentes de entrada e sada de um computador so, em geral, muito mais lentos que a memria do computador. Comumente, buffers de sada so utilizados para aumentar a eficincia de um aplicativo enviando volumes maiores de dados menos vezes, reduzindo, assim, o nmero de vezes que um aplicativo acessa os componentes de entrada e sada do computador.

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

L um objeto (5 de 7) String no servidor Linha 117 Linha 138

Invoca o mtodo Socket close para fechar o socket

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

54

Resumo
ClientTest.java

(2 de 2) Sada do programa

2005 by Pearson Education do Brasil

24.7 Interao cliente/servidor sem conexo com datagramas


Transmisso sem conexo com datagramas:
Nenhuma conexo mantida com um outro computador. Divide a mensagem em partes separadas e as envia como pacotes. Uma mensagem pode chegar na ordem, fora da ordem ou simplesmente no chegar. O receptor coloca mensagens na ordem e as l.

55

2005 by Pearson Education do Brasil

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

Utiliza um DatagramSocket como nosso servidor

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

Linha 57 Linhas 77-79

// 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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

13 } // fim da classe ServerTest

Janela Server depois que o pacote de dados recebido do client

2005 by Pearson Education do Brasil

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" );

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

Cria DatagramSocket para envio e recebimento de pacotes

2005 by Pearson Education do Brasil

80 81 82 83 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

// 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

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

67

Erro comum de programao 24.2


Especificar uma porta que j est em utilizao ou especificar um nmero de porta invlido ao criar um DatagramSocket resulta em uma SocketException.

2005 by Pearson Education do Brasil

24.8 Jogo-da-velha cliente/servidor que utiliza um servidor com multithread


Mltiplas threads:
O servidor utiliza uma thread por jogador.
Permite que cada jogador jogue de maneira independente

68

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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

Cria um array players com 2 elementos

Resumo

TicTacToeServer .java

(3 de 12) ServerSocket para ouvir na porta 12345 Linha 50 Linha 55

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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

(8 de 12) Linhas 200-201

Obtm os fluxos para enviar e receber dados

2005 by Pearson Education do Brasil

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

Envia a marca do jogador

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

Envia uma mensagem indicando que o jogador O est conectado

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

2005 by Pearson Education do Brasil

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

Envia uma mensagem indicando que a jogada invlida


TicTacToeServer .java

Resumo

(12 de 12) Linhas 280-281

suspended = status; // configura o valor do suspenso suspenso 303 } // fim do mtodo setSuspended 304 } // fim da classe Player 305 } // fim da classe TicTacToeServer

2005 by Pearson Education do Brasil

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

13 } // fim da classe classe TicTacToeServerTest

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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 ) );

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

// 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

L o caractere de marca no servidor

2005 by Pearson Education do Brasil

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

L e processa as mensagens no servidor

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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

(8 10) ao Envia a de jogada servidor Linhas 192-193

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

93

Figura 24.17 | Sadas de exemplo do programa cliente/servidor Tic-Tac-

Toe. (Parte 1 de 2.)

2005 by Pearson Education do Brasil

94

Figura 24.17 | Sadas de exemplo do programa cliente/servidor Tic-Tac-

Toe. (Parte 2 de 2.)

2005 by Pearson Education do Brasil

95

24.9 Segurana e redes


Por padro, applets no podem realizar o processamento de arquivo. Em geral, as applets so limitadas quanto ao acesso mquina.
Applets podem se comunicar somente com a mquina a partir da qual foram originalmente baixadas.

API do Java Security:


Applets digitalmente assinadas. Applets com mais privilgios se provenientes de uma fonte confivel.

2005 by Pearson Education do Brasil

24.10 Estudo de caso: Servidor e cliente DeitelMessenger


Salas de bate-papo:
Cada usurio pode postar uma mensagem e ler todas as outras mensagens. Multicast:
Envia pacotes aos grupos de clientes.

96

2005 by Pearson Education do Brasil

24.10.1 DeitelMessengerServer e classes de suporte


DeitelMessengerServer: Sistema de bate-papo on-line. Classes:
DeitelMessengerServer Cliente conecta-se a esse servidor. Interface SocketMessengerConstants Define constantes para nmeros de porta. Interface MessageListener Define o mtodo para receber novas mensagens de bate-papo. Classe MessageReceiver Thread separada ouve as mensagens dos clientes. Classe MulticastSender Thread separada entrega as mensagens enviadas aos clientes.

97

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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)

64 } // fim do mtodo messageReceived 65 } // fim da classe classe DeitelMessengerServer DeitelMessengerServer

Linhas 62-63 Cria e inicia um novo MulticastSender para entregar completeMessage a todos os clientes

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

10 } // fim da interface MessageListener

O mtodo Linha 9 permite messageReceived que uma classe implementadora receba mensagens de bate-papo

2005 by Pearson Education do Brasil

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)

2005 by Pearson Education do Brasil

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

Tenta ler por cinco segundos

Resumo

MessageReceiver .java

(2 de 5) Linha 31

2005 by Pearson Education do Brasil

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71

// ouve mensagens at ser parado while ( keepListening ) { try {

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

Linha 53 lanada se a leitura expirar Linha 55 Linhas 69-70

// 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

2005 by Pearson Education do Brasil

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90

// ignora as mensagens que no contm um nome de usurio // e um corpo de mensagem if ( tokenizer.countTokens() == 2 ) {

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

indica se o usurio deseja Linhas 84-85 sair da sala de bate-papo

2005 by Pearson Education do Brasil

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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 ) {

MulticastSender .java Fecha o DatagramSocket eo

Cria um objeto InetAddress para o endereo de multicast que

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

2005 by Pearson Education do Brasil

24.10.1 DeitelMessengerServer e classes de suporte (Continuao)


Executa DeitelMessengerServerTest:
Altera os diretrios para a localizao adequada. Digite o comando:
java com.deitel.mesenger.sockets.server.DeitelMessengerServerTest

111

2005 by Pearson Education do Brasil

24.10.2 Cliente DeitelMessenger e classes de suporte


Cliente DeitelMessengerServer:
Consiste em vrios componentes:
Interface MessageManager. A classe que implementa a interface MessageManager: Gerencia a comunicao com o servidor. Subclasse Runnable: Ouve mensagens no endereo de multicast do servidor. Uma outra subclasse Runnable: Envia mensagens do cliente para o servidor. Subclasse JFrame: Fornece a GUI do cliente.

112

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

Resumo para enviar

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

Inicia o MessageSender SocketMessage para entregar a (3 de 4)

Linhas 63-64 Linha 65 Linha 66

2005 by Pearson Education do Brasil

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

96 } // fim do mtodo SocketMessageManager

(4 de 4) Cria e inicia um novo Linhas 93-94para MessageSender entregar a nova mensagem em uma thread separada da execuo

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

37 } // fim do catch 38 } // fim do mtodo run 39 } // fim da classe MessageSender

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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 );

na porta MULTICAST_LISTENING_PORT PacketReceiver


.java

// 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

Cria o array de bytes para armazenar o DatagramPacket


2005 by Pearson Education do Brasil

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

Cria um DatagramPacket para armazenar mensagens


PacketReceiver

Resumo

Recebe o pacote.java entrante do endereo de multicast (3 de 4)

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

Linhas 58-59 Linha 63 Linha 78 Linhas 81-82

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

2005 by Pearson Education do Brasil

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

111 } // fim da classe PacketReceiver

2005 by Pearson Education do Brasil

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)

25 import javax.swing.SwingUtilities; 26 import javax.swing.border.BevelBorder; 27

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104

// 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)

2005 by Pearson Education do Brasil

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

(5 de 10) Linhas 128-129

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

DeitelMessengerServer como uma mensagem de bate-papo

2005 by Pearson Education do Brasil

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

(6 de 10) Linha 155

Desconecta-se do servidor de chat quando o usurio fecha a aplicao cliente

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

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

2005 by Pearson Education do Brasil

135

Resumo
DeitelMessenger .java

(2 de 3)

2005 by Pearson Education do Brasil

136

Resumo
DeitelMessenger .java

(3 de 3)

2005 by Pearson Education do Brasil

24.10.2 Cliente DeitelMessenger e classes de suporte (Continuao)


Executa o aplicativo cliente DeitelMessenger:
Altera os diretrios para a localizao adequada. Digite o comando:


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

2005 by Pearson Education do Brasil

Você também pode gostar