Como criar um Chat Multithread com Socket em Java Veja nesse artigo como criar um chat Multithread com Java. Para isso será necessário usar e aplicar conceitos de Thread e Socket, além da programa!o "rientado a "#jetos. $%& $'&
(ma Thread Thread pode pode ser considerada um )lu*o de controle se+uencial dentro de um programa, onde damos algum jo# e ela o realia, provendo maior per)ormance. -m programa!o é muito importante sa#er aplicar )ormas de processamento assncrono, assncrono, pois atualmente temos processadores altamente veloes e n!o sa#emos e*plorá/los devidamente. 0o nosso chat +ue criaremos nesse artigo, a Thread será usada para controlar o )lu*o de mensagens enviadas e rece#idas por um cliente, pois imagina se todos elas )ossem armaenadas numa )ila e processadas unicamente por uma thread1 o servio seria precário e provavelmente ninguém usaria.
O que é Socket Socket é Socket é um meio de comunica!o usado para via#iliar a cone*!o cliente2servidor,, onde um cliente in)orma o endereo de 3P e a cliente2servidor
respectiva porta do servidor. Se este aceitar a cone*!o, ele irá criar um meio de comunica!o com esse cliente. 4ogo, a com#ina!o de Threads e Socket é per)eita para implementa!o de um chat.
OOP 5rente a +uantidade de linguagens orientadas a o#jetos $""& e*istentes, como C6, C77, Java, entre outras, )ica evidente +ue para dominá/las é necessário entender #em os pilares "", como 8erana $por inter)ace e por classe&, -ncapsulamento, Polimor)ismo e 9#stra!o. Se dominar #em esses assuntos, com certea terá mais )acilidade em construir c:digos simples e com +ualidade, tendo #ai*o acoplamento e alta coes!o. 0este artigo nos depararemos com 8erana por inter)ace e classe #ase, a#stra!o e encapsulamento, mas n!o será o )oco do mesmo a#ordar seus conceitos.
9 seguir s!o descritas as responsa#ilidades e comportamentos das classes Server.java e Cliente.java usadas para a constru!o do Chat1 •
Responsabilidade e comportamentos do Server.java: o servidor servirá como unidade centraliadora de todas as cone*;es rece#idas via socket e terá como responsa#ilidade o envio de uma mensagem $rece#ida de um cliente& para todos os demais conectados no servidor.
•
Responsabilidade e comportamentos do Client.java: Cada usuário criará uma inst>ncia do cliente e )ará uma cone*!o com o servidor socket. " cliente deverá in)ormar o endereo do server socket e a respectiva porta, por isso é necessário e*ecutar o Server.java antes.
Lembrese: escolha uma porta +ue n!o esteja sendo usada para a e*ecu!o do server socket e certi)i+ue/se +ue o )ire?all ou algum antivrus n!o esteja #lo+ueando a porta escolhida. Para esse artigo de)inimos como @ABD.
0a Lista!em " temos a declara!o dos pacotes usados na classe servidor.java. Veja +ue usamos EstreamsF, EcollectionsF e classes para a constru!o de )ormulários.
Lista!em ". Geclara!o dos imports import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayLit; import javax.!in".#La$el; import javax.!in".#Option%ane; import javax.!in".#&ext'ield;
9 seguir temos a declara!o da classe servidor.java. Veja +ue ela e*tends Thread, logo é um tipo de Thread, adotando todos os comportamentos e propriedades desta classe pu$lic cla Servidor extend &(read )
0a Lista!em # temos a declara!o dos atri#utos estáticos e de inst>ncias da classe servidor.java. " atri#uto EclientesF é usado para armaenar o Hu))eredIriter de cada cliente conectado e o server socket é usado para a cria!o do servidor, +ue teoricamente deve ser )eita apenas uma ve.
Lista!em #. 9tri#utos estáticos private tatic ArrayLit*BufferedWriter+cliente; private tatic ServerSocket erver; private Strin" nome; private Socket con; private InputStream in; private InputStreamReader inr; private BufferedReader $fr;
0a Lista!em $ temos a declara!o do método construtor, +ue rece#e um o#jeto socket como par>metro e cria um o#jeto do tipo Hu))eredeader, +ue aponta para o stream do cliente socket.
Lista!em $. Geclara!o do método construtor ,-- /todo contrutor - 0param com do tipo Socket -, pu$lic Servidor1Socket con2) t(i.con 3 con; try ) in
3 con."etInputStream12;
inr 3 ne! InputStreamReader1in2;
$fr 3 ne! BufferedReader1inr2; 4 catc( 1IOException e2 )
e.printStack&race12; 4
4
9 Lista!em % mostra a declara!o do método ErunF1 toda ve +ue um cliente novo chega ao servidor, esse método é acionado e alocado numa Thread e tam#ém )ica veri)icando se e*iste alguma mensagem nova. Caso e*ista, esta será lida e o evento EsentToAll F será acionado para enviar a mensagem para os demais usuários conectados no chat.
Lista!em %. Geclara!o do método run ,-- /todo run -, pu$lic void run12) try) Strin" m"; OutputStream ou 3
t(i.con."etOutputStream12;
Writer ou! 3 ne! OutputStreamWriter1ou2; BufferedWriter $f! 3 ne! BufferedWriter1ou!2; cliente.add1$f!2; nome 3 m" 3 $fr.readLine12; !(ile156Sair6.e7ualI"nore8ae1m"2 99 m" 53 null2 ) m" 3 $fr.readLine12; end&oAll1$f!: m"2;
Sytem.out.println1m"2; 4 4catc( 1Exception e2 )
e.printStack&race12; 4
4
0a Lista!em & temos a declara!o do método EsendToAll F.
Lista!em &. Geclara!o do método sendTo9ll ,-- - /todo uado para enviar mena"em para todo o client - 0param $!Saida do tipo BufferedWriter - 0param m" do tipo Strin" - 0t(ro! IOException -, pu$lic void end&oAll1BufferedWriter $!Saida: Strin" m"2 t(ro! IOException ) BufferedWriter $!S; for1BufferedWriter $! cliente2) $!S 3 1BufferedWriter2$!; if151$!Saida 33 $!S22) $!.!rite1nome < 6 =+ 6 < m"<6>r>n62;
$!.flu(12; 4 4
4
9 Lista!em ' mostra a declara!o do método main, +ue ao iniciar o servidor, )ará a con)igura!o do servidor socket e sua respectiva porta. Veja +ue ele comea criando uma janela para in)ormar a porta e depois entra no “while(true)” . 0a linha “server.accept()” o sistema )ica #lo+ueado até +ue um cliente socket se conecte1 se ele )ier isso é criada uma nova Thread do tipo servidor.
4em#re/se +ue a classe servidor é um tipo de Thread e é iniciada na instru!o “t.start()” . -nt!o o controle do )lu*o retorna para a linha “server.accept()” e aguarda outro cliente se conectar.
Lista!em '. Geclara!o do método main ,--- /todo main - 0param ar" -, pu$lic tatic void main1Strin" ?@ar"2 ) try) ,,8ria o o$jeto necerio para intnciar o ervidor #La$el l$lea"e 3 ne! #La$el16%orta do Servidor62; #&ext'ield txt%orta 3 ne! #&ext'ield16CDFG62; O$ject?@ text 3 )l$lea"e: txt%orta 4; #Option%ane.(o!ea"eHialo"1null: text2; erver 3 ne! ServerSocket1Inte"er.pareInt1txt%orta."et&ext1222; cliente 3 ne! ArrayLit*BufferedWriter+12; #Option%ane.(o!ea"eHialo"1null:6Servidor ativo na porta 6< txt%orta."et&ext122; !(ile1true2) Sytem.out.println16A"uardando conexo...62; Socket con 3 erver.accept12; Sytem.out.println168liente conectado...62; &(read t 3 ne! Servidor1con2;
t.tart12; 4 4catc( 1Exception e2 ) e.printStack&race12; 4 4,, 'im do m/todo main
4 ,,'im da clae
9 Lista!em ( mostra a declara!o dos pacotes usados na classe cliente.java.
Lista!em (. Geclara!o dos 3mports import java.a!t.8olor; import java.a!t.event.ActionEvent; import java.a!t.event.ActionLitener; import java.a!t.event.JeyEvent; import java.a!t.event.JeyLitener; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.net.Socket; import javax.!in".-;
9 seguir temos a declara!o da classe Cliente.java1 pu$lic cla 8liente extend #'rame implement ActionLitener: JeyLitener )
Para a constru!o do )ormulário )oram usados o#jetos do pacote java*.s?ing. 9 Lista!em ) mostra a declara!o dos atri#utos estáticos e de inst>ncias da classe Cliente.java.
Lista!em ). Geclara!o dos atri#utos private tatic final lon" erialKerionIH 3 CL; private #&extArea texto; private #&ext'ield txt"; private #Button $tnSend; private #Button $tnSair; private #La$el l$lMitorico; private #La$el l$l"; private #%anel pnl8ontent; private Socket ocket; private OutputStream ou ; private Writer ou!; private BufferedWriter $f!;
private #&ext'ield txtI%; private #&ext'ield txt%orta; private #&ext'ield txtNome;
9o e*ecutar a classe cliente aparecerá uma tela para o usuário in)ormar alguns par>metros como o 3P do servidor, a porta e o nome +ue será visto para os demais usuários no chat. 0o c:digo está de)inido como padr!o o 3P @AK.'.'.@, porta @ABD e nome cliente.
"#serve tam#ém +ue a classe herda de J5rame, possi#ilitando a cria!o de )ormulários e implementa!o das inter)aces 9ction4istener e Le4istener para prover a;es nos #ot;es e a;es das teclas, respectivamente.
9 Lista!em * mostra a declara!o do método construtor, +ue veri)ica os o#jetos sendo instanciados para a constru!o da tela do chat. 4em#re/se +ue cada cliente deverá ser uma inst>ncia independente.
Lista!em *. Geclara!o do método construtor pu$lic 8liente12 t(ro! IOException) #La$el l$lea"e 3 ne! #La$el16Kerificar562; txtI% 3 ne! #&ext'ield16CD.P.P.C62; txt%orta 3 ne! #&ext'ield16CDFG62; txtNome 3 ne! #&ext'ield168liente62; O$ject?@ text 3 )l$lea"e: txtI%: txt%orta: txtNome 4; #Option%ane.(o!ea"eHialo"1null: text2; pnl8ontent 3 ne! #%anel12; texto
3 ne! #&extArea1CP:DP2;
texto.etEdita$le1fale2; texto.etBack"round1ne! 8olor1DFP:DFP:DFP22; txt" l$lMitorico l$l" $tnSend
3 ne! #&ext'ield1DP2; 3 ne! #La$el16MitQrico62; 3 ne! #La$el16ena"em62; 3 ne! #Button16Enviar62;
$tnSend.et&ool&ip&ext16Enviar ena"em62;
$tnSair
3 ne! #Button16Sair62;
$tnSair.et&ool&ip&ext16Sair do 8(at62;
$tnSend.addActionLitener1t(i2;
$tnSair.addActionLitener1t(i2;
$tnSend.addJeyLitener1t(i2;
txt".addJeyLitener1t(i2; #Scroll%ane croll 3 ne! #Scroll%ane1texto2;
texto.etLineWrap1true2; pnl8ontent.add1l$lMitorico2;
pnl8ontent.add1croll2;
pnl8ontent.add1l$l"2;
pnl8ontent.add1txt"2;
pnl8ontent.add1$tnSair2;
pnl8ontent.add1$tnSend2;
pnl8ontent.etBack"round18olor.LIM&RAT2; texto.etBorder1Border'actory.createEtc(edBorder18olor.BLE:8olo
r.BLE22;
txt".etBorder1Border'actory.createEtc(edBorder18olor.BLE:
8olor.BLE22; et&itle1txtNome."et&ext122;
et8ontent%ane1pnl8ontent2;
etLocationRelative&o1null2;
etReiUa$le1fale2;
etSiUe1DGP:PP2;
etKii$le1true2;
etHefault8loeOperation1EVI&ON8LOSE2;
4
" método da Lista!em "+ é usado para conectar o cliente com o servidor socket. 0esse método é possvel visualiar a cria!o do socket cliente e dos streams de comunica!o.
Lista!em "+. Geclara!o do método conectar ,--- /todo uado para conectar no erver ocket: retorna IO Exception cao d al"um erro. - 0t(ro! IOException -, pu$lic void conectar12 t(ro! IOException)
ocket 3 ne! Socket1txtI%."et&ext12:Inte"er.pareInt1txt%orta."et&ext1222; ou 3 ocket."etOutputStream12; ou! 3 ne! OutputStreamWriter1ou2; $f! 3 ne! BufferedWriter1ou!2; $f!.!rite1txtNome."et&ext12<6>r>n62; $f!.flu(12; 4
9 Lista!em "" tem o método usado para enviar mensagens do cliente para o servidor socket. 9ssim, toda ve +ue ele escrever uma mensagem e apertar o #ot!o E-nterF, esta será enviada para o servidor.
Lista!em "". Geclara!o do método enviar mensagem ,--- /todo uado para enviar mena"em para o erver ocket - 0param m" do tipo Strin" - 0t(ro! IOException retorna IO Exception cao d al"um erro. -, pu$lic void enviarena"em1Strin" m"2 t(ro! IOException) if1m".e7ual16Sair622) $f!.!rite16Heconectado >r>n62; texto.append16Heconectado >r>n62;
4ele)
$f!.!rite1m"<6>r>n62; texto.append1 txtNome."et&ext12 < 6 diU =+ 6 <
txt"."et&ext12<6>r>n62; 4
$f!.flu(12;
txt".et&ext1662;
4
0a Lista!em "# temos o método usado para escutar $rece#er& mensagens do servidor. Toda ve +ue alguém enviar uma, o método
será processado pelo servidor e envia para todos os clientes conectados, por isso a necessidade do c:digo.
Lista!em "#. Geclara!o do método escutar ,- - /todo uado para rece$er mena"em do ervidor - 0t(ro! IOException retorna IO Exception cao d al"um erro. -, pu$lic void ecutar12 t(ro! IOException) InputStream in 3 ocket."etInputStream12; InputStreamReader inr 3 ne! InputStreamReader1in2; BufferedReader $fr 3 ne! BufferedReader1inr2; Strin" m" 3 66; !(ile156Sair6.e7ualI"nore8ae1m"22 if1$fr.ready122) m" 3 $fr.readLine12;
if1m".e7ual16Sair622 texto.append16Servidor caiu5 >r>n62;
ele
texto.append1m"<6>r>n62; 4
4
" método da Lista!em "$ é usado para desconectar do server socket. 0ele o sistema apenas )echa os streams de comunica!o.
Lista!em "$. Geclara!o do método sair ,--- /todo uado 7uando o uurio clica em air - 0t(ro! IOException retorna IO Exception cao d al"um erro. -, pu$lic void air12 t(ro! IOException) enviarena"em16Sair62;
$f!.cloe12;
ou!.cloe12;
ou.cloe12;
ocket.cloe12;
4
" método usado para rece#er as a;es dos #ot;es dos usuários é visto na Lista!em "%. 0ele )oi )eito um chaveamento1 se o usuário pressionar o #ot!o EsendF ent!o será enviada uma mensagem, sen!o será encerrado o chat.
Lista!em "%. Geclara!o do método actionPer)ormed 0Override pu$lic void action%erformed1ActionEvent e2 ) try )
if1e."etAction8ommand12.e7ual1$tnSend."etAction8ommand1222
enviarena"em1txt"."et&ext122; ele
if1e."etAction8ommand12.e7ual1$tnSair."etAction8ommand1222
air12; 4 catc( 1IOException eC2 ) ,, &OHO Auto="enerated catc( $lock
eC.printStack&race12; 4
4
" método da Lista!em "& é acionado +uando o usuário pressiona E-nterF, veri)icando se o ke code é o -nter. Caso seja, a mensagem é enviada para o servidor.
Lista!em "&. Geclara!o do método kePressed 0Override pu$lic void key%reed1JeyEvent e2 ) if1e."etJey8ode12 33 JeyEvent.KJEN&ER2)
try )
enviarena"em1txt"."et&ext122; 4 catc( 1IOException eC2 ) ,, &OHO Auto="enerated catc( $lock
eC.printStack&race12; 4 4
4 0Override pu$lic void keyReleaed1JeyEvent ar"P2 ) ,, &OHO Auto="enerated met(od tu$ 4 0Override pu$lic void key&yped1JeyEvent ar"P2 ) ,, &OHO Auto="enerated met(od tu$ 4
9 Lista!em "' mostra o método main, onde é criado apenas um cliente e s!o con)igurados os métodos conectar e escutar.
Lista!em "'. Geclara!o do método main pu$lic tatic void main1Strin" ?@ar"2 t(ro! IOException) 8liente app 3 ne! 8liente12;
app.conectar12;
app.ecutar12;
4
Gepois do c:digo implementado na 3G- Eclipse ou Netbeans, temos duas classes1 a Servidor.java e a Cliente.java. -*ecute uma ve a classe Servidor.java e a classe Cliente.java +uantas vees achar necessário, porém, se e*ecutar apenas uma ve, vocN n!o verá sua mensagem sendo enviada para ninguém.
metros necessários. 3n)orme o nOmero da porta, con)orme mostra a ,i!ura ".
,i!ura ". 3nput para in)ormar o nOmero da porta onde o servidor socket rece#erá as cone*;es.
9o e*ecutar um cliente tam#ém será necessário in)ormar alguns par>metros como a porta e o endereo de 3P do servidor socket, como vemos na ,i!uras #.
,i!ura #. 3nputs do 3P do servidor socket, a porta e o nome +ue será visto por vocN e pelos outros usuários.
,i!ura $. Chat em e*ecu!o.
9p:s e*ecutar o servidor e dois ou mais clientes será possvel conversar com todos eles. epare na primeira tela da ,i!ura $ , em +ue o Paul comea a conversa.
Vimos como é simples a constru!o #ásica de um chat, desde de +ue a ideia de Thread e Socket seja #em compreendida.
-spero +ue tenham gostado