Dúvidas Básicas de Socket

79 respostas
S

Fala galera, Tudo bom?

Estou estudando um tutorial de chat e ja consegui enviar e receber mensagens!
Porém, nao entendi uma parte deste código abaixo ,

Exatamente essa parte aqui :
Scanner in = new Scanner(socket.getInputStream());
           PrintWriter out = new PrintWriter(socket.getOutputStream());

Não entendi muito bem o que esta acontecendo ^
Podem me ajudar?

Segue o método run do código;

@Override
    public void run() {
       try{
           Scanner chat = new Scanner(System.in);
           Scanner in = new Scanner(socket.getInputStream());
           PrintWriter out = new PrintWriter(socket.getOutputStream());
           
           while(true)
           {
               String input = chat.nextLine();
               out.println(input);
               out.flush();
               if(in.hasNext())
               {
                   System.out.println("" + in.nextLine());
               }
           }
           
       } catch(Exception e)
       {
            System.out.println(e.getMessage());
            e.printStackTrace();
       }
        
    }

Estudei o código aqui :

http://forum.codecall.net/topic/67704-server-and-client-chat-tutorial/

79 Respostas

B

Boa tarde.

O método socket.getInputStream() é responsável por retornar o fluxo de entrada da Socket, para a leitura do que é enviado pela outra ponta.

No caso, você optou por utilizar o Scanner, pois ele oferece métodos mais “convenientes” para a leitura de sua Stream, como ler próximo número, próxima linha, etc. Ao invés de trabalhar diretamente com os bytes que são recebidos.

O mesmo para o PrintWriter para envio diretamente de linhas (println) à sua socket.

Espero ter ajudado.

Valeu!
Bruno

M

// Criada uma instância de Scanner que lê dados a partir de uma instância // de InputStream. Usa-se o método getInputStream para obter o objeto // InputStream associado ao Socket. Scanner in = new Scanner(socket.getInputStream()); // Criada uma instância de PrintWriter que escreve dados em uma instância // de OutputStream. Usa-se o método getOutputStream para obter o objeto // OutputStream associado ao Socket. PrintWriter out = new PrintWriter(socket.getOutputStream());

InputStream e OutputStream são classes abstratas que definem os comportamentos básico necessários às operações de leitura e escrita de bytes, respectivamente. A classe Scanner e a classe PrtinWriter disponibilizam operações para serem realizadas sobre objetos InputStream e OutputStream, no caso, leitura e escrita de texto formatado.

S

Muito Obrigado gente, acho que saquei.

Mais uma pergunta,Tem outro Objeto que posso usar alem desses dois ? O Print e o Scanner?

V

O DataInputStream e o DataOutputStream, para o caso de protocolos binários.
Protocolos binários costumam a ser mais eficientes e mais fáceis de implementar.

Porém, não são legíveis a olho nú (o que muitas vezes é uma vantagem).

S

ViniGodoy:
O DataInputStream e o DataOutputStream, para o caso de protocolos binários.
Protocolos binários costumam a ser mais eficientes e mais fáceis de implementar.

Porém, não são legíveis a olho nú (o que muitas vezes é uma vantagem).

Boa noite Viny!!

Como assim Protocolos Binários?

V

Protocolos onde não é transmitido a informação na forma de texto, mas sim, diretamente em sua forma binária.

É exatamente o mesmo conceito de um arquivo binário e de um arquivo texto. Tente ler o que conteúdo de qualquer arquivo .exe e você vai ver do que estou falando.

S

ViniGodoy:
Protocolos onde não é transmitido a informação na forma de texto, mas sim, diretamente em sua forma binária.

É exatamente o mesmo conceito de um arquivo binário e de um arquivo texto. Tente ler o que conteúdo de qualquer arquivo .exe e você vai ver do que estou falando.

Hmm.Entendi.
No caso, então no caso o DataInputStream receberia o socket.getInputStream como parâmetro,por exemplo ?

V

Por exemplo, num protocolo de texto, o número 2.120.120.123, se transmitido sem os pontinhos ocuparia 10 bytes, isso se você codificar o texto em UTF-8.
Em um protocolo binário, você codificaria essa informação na forma de um int, e ela ocuparia apenas 4 bytes.

V

Andre Lopes:
Hmm.Entendi.
No caso, então no caso o DataInputStream receberia o socket.getInputStream como parâmetro,por exemplo ?

Sim. Ele seria usado no lugar do PrintWriter e do Scanner (não foi o que você perguntou)?

Dê uma olhada nesse tópico, que fala mais sobre o assunto:

S

ViniGodoy:
Por exemplo, num protocolo de texto, o número 2.120.120.123, se transmitido sem os pontinhos ocuparia 10 bytes, isso se você codificar o texto em UTF-8.
Em um protocolo binário, você codificaria essa informação na forma de um int, e ela ocuparia apenas 4 bytes.

Ahh Entendi.
Agora sim rsrs :smiley: , Valeu Viny!!!

Valeu gente!!

V

O PrintWriter e o Scanner transmitem texto. Isso é, eles fazem o socket esperar constantemente por um separador, no caso, a quebra de linha, \n.
O DataInputStream e o DataOutputStream não dependem de separador. Por isso a preocupação de transmitir tamanhos de dados, descrita no tópico que linkei.

Protocolos binários são muitíssimo mais eficientes do que protocolos texto.

São exemplos de protocolos binários famosos na internet o DHCP, o SSH e os protocolos de aplicações em geral, como Messenger, Skype, Wow…
São exemplos de protocolos texto famosos o FTP, HTTP, SMTP, POP3 e o SIP.

S

Só mais uma pergunta gente,
Se é OutputStream, como que o InputStream vai saber, que o que esta chegando é uma String, um arquivo, uma música … etc… ?

Como que é feito isso ?

V

Não vai. Você irá colocar algum campo em sua mensagem que diga isso.

S

Entendi.

Consegui fazer uma view que mostra a mensagens que os usuários digitam, etc…

Mas, agora tenho uma outra dúvida!
O servidor tem um arrayList dos usuários conectados!
Como eu faço pra enviar esse arrayList pro usuario, pra ele saber quem esta conectado?

B

Andre Lopes:
Entendi.

Consegui fazer uma view que mostra a mensagens que os usuários digitam, etc…

Mas, agora tenho uma outra dúvida!
O servidor tem um arrayList dos usuários conectados!
Como eu faço pra enviar esse arrayList pro usuario, pra ele saber quem esta conectado?

Olá.

Tente dar uma estudada em Serialização de objetos

Você transforma seu objeto em bytes (serializa) na ponta de origem, transfere via stream/socket e na outra ponta você deserializa o que veio - recebendo uma cópia exata do seu objeto.

V

Você cria uma mensagem para isso.

Se seu protocolo for texto, poderia ser uma mensagem com todos os nomes separados por vírgula.

S

No caso de Serialização, eu preciso criar um novo socket somente pra receber o objeto arrayList ?
Porque, o único socket que tenho é pra receber as mensagens. Como que vou diferenciar uma mensagem de um array?
If( getInput == String) ???

Por exemplo :

V

Você não vai enviar o array inteiro. Vai enviar uma mensagem, descrevendo o conteúdo do array. O outro lado recebe essa mensagem e refaz o array.

S

Mas como eu faço isso?
Porque eu só sei usar o PrintWriter pra enviar uma String e receber ela!

Como que vou saber que é uma String ou um array?

V

É só criar regrinhas na sua String. Essas regrinhas são o tal do protocolo.

Por exemplo, vamos supor que você queira transmitir o nome de todos os participantes de uma conversa. Você poderia dizer que a mensagem que transmite isso começa com o texto “nomes:” seguido de todos os nomes separados por vírgula. Exemplo:

nomes: Bruno,Vinicius

Agora bastaria separar essa String usando split.

Vamos pegar um exemplo mais complexo. Agora o participante Vinicius quer mandar uma mensagem apenas para o Bruno, não para todos do chat. Você poderia definir que a expressão “cochichar para:” seria seguida do nome de quem irá receber a mensagem, seguido então da mensagem. Por exemplo:

cochichar para: Bruno: Olá bruno!

Perceba que para um sistema, haverá dezenas de mensagens como essas. O importante é que você pense no seu sistema e organize essas mensagens antes de começar a implementação do resto.
Aliás, se você lesse o tópico que linkei, veria que lá tem um exemplo de mensagem para montar uma lista de diretórios.

S

Ahh valeu Viny, nao tinha Visto aquele Link!!

Agora saquei.
Vou imprimir ele e ler com calma amanhã!

Mas tenho uma outra dúvida!!
Como que os programadores fazem com jogos? Por exemplo, enviar Tiles, Posições… etc?
È usado também essa lógica de protocolo? Ou algum outro tipo de lógica?

V

Sempre que se faz uma aplicação socket, especifica-se um protocolo.

No caso, eu prefiro usar protocolos binários.
Mas sim, existe uma mensagenzinha para cada informação que você queira transmitir via rede.

Eu não recomendo usar ObjectOutputStream ou ObjectInputStream.
É importante ter controle sobre o que é enviado em seu protocolo.

Essas classes podem até facilitar no início, mas se tornam um inferno de manutenção com o tempo.

S

ViniGodoy:
Sempre que se faz uma aplicação socket, especifica-se um protocolo.

No caso, eu prefiro usar protocolos binários.
Mas sim, existe uma mensagenzinha para cada informação que você queira transmitir via rede.

Ah oK!
Vou começar com esse então!
Ja imprimi aqui, e vou ler com calma amanhã :smiley:

S

Mais uma dúvida rsrs

Eu estou fazendo assim o projeto :

Enviar Mensagem :
"Enviar Mensagem : " + msg

O que esta entre aspas é o sinal de que é uma mensagem

//

Enviar Array :
"Lista de usuarios : " + list

Sendo que list é o objeto array

//

Esta ficando correto assim ?

S

Na verdade , mudei de idéia.
Vou usar o Byte mesmo..

Eu só nao entendi como fazer isso em código.
--
Vamo supor

Byte de Código = 0 .: Mensagem

no Projeto Cliente, em uma certa classe, seria assim!? :

public ByteArrayOutputStream codificarMensagem(String mensagem)
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(0);
dos.writeChars(mensagem);
 enviarMensagem(bos);
//return bos;
}

public void enviarMensagem(ByteArrayOutputStream mensagem)
{

byte[] msg = mensagem.getByteArray();
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.write.Int(msg.lenght);
out.write(msg.toByteArray());
out.flush();
}

Assim mesmo ?

S

Ahh, mais uma pergunta.
Fiquei lendo o Tutorial do Viny, várias vezes. Imprimi, grifei.E até consegui implementar pra enviar.
MAS,
como devo fazer pra ler?

Tipo :

if( primeiroByte == 0)

{

lermensagem();

} else if 

Como que eu faço isso???

V
no Projeto Cliente, em uma certa classe, seria assim!?

Isso mesmo.

E para ler:

int primeiroByte = dataInputStream.read(); //Lê um byte if (primeiroByte == 0) { //Faz qualquer coisa }

S
ViniGodoy:
no Projeto Cliente, em uma certa classe, seria assim!?

Isso mesmo.

E para ler:

int primeiroByte = dataInputStream.read(); //Lê um byte
if (primeiroByte == 0) {
   //Faz qualquer coisa
}

Ficou Assim!!
Agora como leio a mensagem? o readLine esta deprecado e nao tem hasNext();

@Override
    public void run() {

        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            int read = dis.read();
            
                if (read == 0)// È uma Mensagem
                {
            
                }

        } catch (Exception e) {
            System.out.println(e.getMessage());
            //e.printStackTrace();
        }

    }
V

Você lê usando os métodos readByte(), readInt(), etc… na mesma ordem que você gravou, você lè.

Em protocolos binários, não existe mais o conceito de “linhas”. Esqueça isso, os dados estão lado-a-lado, basta lê-los na mesma ordem que você gravou.

S

ViniGodoy:
Você lê usando os métodos readByte(), readInt(), etc… na mesma ordem que você gravou, você lè.

Em protocolos binários, não existe mais o conceito de “linhas”. Esqueça isso, os dados estão lado-a-lado, basta lê-los na mesma ordem que você gravou.

Assim Viny?

@Override
    public void run() {

        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            int read = dis.read();
            
                if (read == 0)// È uma Mensagem
                {
                    String input = dis.readUTF();
                }

        } catch (Exception e) {
            System.out.println(e.getMessage());
            //e.printStackTrace();
        }

    }
V

Isso mesmo.
Se a sua mensagem 0 tiver um UTF-8 no início, é assim mesmo.

S
ViniGodoy:
Isso mesmo. Se a sua mensagem 0 tiver um UTF-8 no início, é assim mesmo.

Eu não sei se ela tem UTF-8 no inicio...

Meu transmissor de mensagem 0 esta assim :

public void codificarMensagemEtransmitir(String mensagem) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            DataOutputStream dos = new DataOutputStream(bos);
            dos.writeByte(0);
            dos.writeChars(mensagem);
            enviarMensagem(bos);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void enviarMensagem(ByteArrayOutputStream mensagem) throws IOException {

        byte[] msg = mensagem.toByteArray();
        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
        out.writeInt(msg.length);
        out.write(msg);
        out.flush();
        System.out.println("Bytes Enviados");
    }

Como que devo ler??? aaaa que confusão

V
Veja a mensagem que você montou:

a) Um INT contendo o tamanho do pacote;

b) Um BYTE contendo o número 0 (que pode ser o ID da mensagem);

c) Caracteres até o final da mensagem.
Como vc deve ler:

a) Leia o INT;

b) Leia a quantidade de bytes que esse int indica, gravando num buffer;

c) Leia desse buffer o primeiro byte. Isso indica o tipo da mensagem.

d) No caso da mensagem 0, leia os demais bytes para dentro de uma String.

Os passos a e b podem estar numa função separada, para todas as mensagens do seu protocolo.

S
<blockquote><div class="quote-author">ViniGodoy:</div>Veja a mensagem que você montou:

a) Um INT contendo o tamanho do pacote;

b) Um BYTE contendo o número 0 (que pode ser o ID da mensagem);

c) Caracteres até o final da mensagem.
Como vc deve ler:

a) Leia o INT;

b) Leia a quantidade de bytes que esse int indica, gravando num buffer;

c) Leia desse buffer o primeiro byte. Isso indica o tipo da mensagem.

d) No caso da mensagem 0, leia os demais bytes para dentro de uma String.

Os passos a e b podem estar numa função separada, para todas as mensagens do seu protocolo.

Obrigadão Viny, mas ainda tenho dúvidas…
a) e d) não são dificeis mas o b) e C) nao tenho a mínima noção de como fazer >.<

Como vou saber quantos bytes dizem o tamanho do pacote?
Tipo, la dentro vai estar 010101010101010000000000000000000000011111111111

O Tamanho pode ser praticamente qualquer numero.
E em que tipo de Buffer Devo Guardar?

E como vou transformar só uma parte em String???

S
<blockquote><div class="quote-author">Andre Lopes:</div><blockquote><div class="quote-author">ViniGodoy:</div>Veja a mensagem que você montou:

a) Um INT contendo o tamanho do pacote;

b) Um BYTE contendo o número 0 (que pode ser o ID da mensagem);

c) Caracteres até o final da mensagem.
Como vc deve ler:

a) Leia o INT;

b) Leia a quantidade de bytes que esse int indica, gravando num buffer;

c) Leia desse buffer o primeiro byte. Isso indica o tipo da mensagem.

d) No caso da mensagem 0, leia os demais bytes para dentro de uma String.

Os passos a e b podem estar numa função separada, para todas as mensagens do seu protocolo.

Obrigadão Viny, mas ainda tenho dúvidas…
a) e d) não são dificeis mas o b) e C) nao tenho a mínima noção de como fazer >.<

Como vou saber quantos bytes dizem o tamanho do pacote?
Tipo, la dentro vai estar 010101010101010000000000000000000000011111111111

O Tamanho pode ser praticamente qualquer numero.
E em que tipo de Buffer Devo Guardar?

E como vou transformar só uma parte em String???

Ahh , espera!
È só um byte que diz o tamanho? Se for isso… então é Total de Bytes - 2 , que devem ser lidos ?

S
Andre Lopes:
Andre Lopes:
ViniGodoy:
Veja a mensagem que você montou: a) Um INT contendo o tamanho do pacote; b) Um BYTE contendo o número 0 (que pode ser o ID da mensagem); c) Caracteres até o final da mensagem.

Como vc deve ler:
a) Leia o INT;
b) Leia a quantidade de bytes que esse int indica, gravando num buffer;
c) Leia desse buffer o primeiro byte. Isso indica o tipo da mensagem.
d) No caso da mensagem 0, leia os demais bytes para dentro de uma String.

Os passos a e b podem estar numa função separada, para todas as mensagens do seu protocolo.

Obrigadão Viny, mas ainda tenho dúvidas...
a) e d) não são dificeis mas o b) e C) nao tenho a mínima noção de como fazer >.<

Como vou saber quantos bytes dizem o tamanho do pacote?
Tipo, la dentro vai estar 010101010101010000000000000000000000011111111111

O Tamanho pode ser praticamente qualquer numero.
E em que tipo de Buffer Devo Guardar?

E como vou transformar só uma parte em String?????

Ahh , espera!
È só um byte que diz o tamanho? Se for isso.. então é Total de Bytes - 2 , que devem ser lidos ?

Tentei isso aqui, nao deu certo :P

@Override
    public void run() {

        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            int read = dis.read();

            if (read == 0)// È uma Mensagem
            {
                String input = &quot;oi&quot;;
                for (int i = 0; i &lt; dis.readInt(); i++) {
                    input = input + dis.read();
                }
                
                System.out.println(&quot;&quot; + input);
            }
            
            

        } catch (Exception e) {
            System.out.println(e.getMessage());
            //e.printStackTrace();
        }
V

Você vai saber o tamanho pq foi você que escreveu os bytes lá.

No seu protocolo, sua mensagem COMEÇA com um int, contendo o tamanho da mensagem. Pelo menos, é o que o método sendMessage faz.

Então, seu PRIMEIRO comando tem que ser um readInt:

int tamanho = dis.readInt(); //Lê o tamanho da mensagem.

Em seguida, você pode criar um buffer, e fazer a leitura do pacote todo para lá. O processo é um pouco mais trabalhoso do que parece, já que num socket, você nunca sabe quantos bytes virão exatamente a cada leitura. Precisa fazer um for.

No início do bloco desses bytes lidos, virá o identificador da mensagem. Que tem um único byte de tamanho.
Depois disso, os chars da mesagem.

Como você sabe o número de bytes? Estudando a documentação:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

Observe que ele fala quantos bits (portanto, quantos bytes) ocupa na memória cada tipo de dado. Em resumo:
1 long = 8 bytes
1 int = 4 bytes
1 short = 2 bytes
1 byte = 1 byte
1 float = 4 bytes
1 double = 8 bytes
1 String = varia. Por isso geralmente vamos transmitir o tamanho da String antes, ou um terminador, como o \n.

Sem entender como os dados são codificados, é difícil escrever um protocolo, ou mesmo um programa para gravar e ler um arquivo binário.

Mais importante do que isso, se você for estudar como comunicar uma aplicação Windows com um Mac, você teria que saber não só quantos bytes os dados ocupam em cada plataforma, mas também a ordem que eles são gravados na memória do computador (que pode ser little ou big endian).

Pode parecer complicado mas, após vencer a teoria básica, você vai ver que é mais simples do que ficar fazendo parse de arquivos texto. Pois os dados já estão lá. Se você enviar um dado gravado assim:

out.writeByte(MSG_ID); out.writeInteger(usuario.id); out.writeFloat(usuario.salario);

Vai ler assim:

int id = out.readByte(); if (msg == MSG_SALARIO) { usuario.setId(in.readInteger()); usuario.setSalario(in.readFloat()); }

S

Acho que entendi.
Então eu escrevi o tamanho em 4 bytes porque é Int!
Em seguida eu escrevi mais 4 bytes dizendo o tipo da mensagem?
Eu uso esses 4 bytes do tamanho e guardo em um int. Esse int sera o meu limite do for.

Lerei tantos bytes o limite disser.


Acertei ? :smiley:


Obrigadão Viny, deve ter dado trabalho escrever tudo isso.
Estou até Imprimindo pra deixar guardado numa pasta que eu tenho o.o

V

Você começou, de cara, escrevendo um int (4 bytes) cujo conteúdo era o tamanho da mensagem.

E, sim, esse valor você vai usar no seu for.

S
ViniGodoy:
Você começou, de cara, escrevendo um int (4 bytes) cujo conteúdo era o tamanho da mensagem.

E, sim, esse valor você vai usar no seu for.

Alguma Coisa esta faltando rsrs.
Mas acho que ja melhorou :

@Override
    public void run() {

        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            
            int tamanho = dis.readInt(); // Como é Read Int, acredito que ja leia 4 Bytes, correto?
            int tipoMensagem = dis.readInt(); // Tipo de mensagem
            
            if (tipoMensagem == 0)// È uma Mensagem
            {
                String input = &quot;&quot;;
                
                for (int i = 0; i &lt; tamanho; i++) {
                    input = input + dis.read();
                }
                
                System.out.println(&quot;&quot; + input);
            }
            
            

        } catch (Exception e) {
            System.out.println(e.getMessage());
            //e.printStackTrace();
        }

    }
S

Agora esta quase funcionando VinY!

@Override
    public void run() {

        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
                             
            int tamanho = dis.readInt(); // Como é Read Int, acredito que ja leia 4 Bytes, correto?
            int tipoMensagem = dis.read(); // Tipo de mensagem
            
            System.out.println(tamanho);
            System.out.println(tipoMensagem);
            
            if (tipoMensagem == 0)// È uma Mensagem
            {
                String input = "";
                
                for (int i = 0; i < tamanho; i++) {
                    input = input + dis.readChar();
                    //System.out.println("" + input); // Esta linha imprime aos poucos, certinho.... Mas 
                }
                
                System.out.println("" + input); // Esta debaixo imprime null -.-
            }
            
            

        } catch (Exception e) {
            System.out.println(e.getMessage());
            //e.printStackTrace();
        }

    }
V

Já rodou com o depurador para ver quando a String ficou null?

Uma coisa, seu i provavelmente não irá começar em 0, e sim em 1. Isso porque um byte já foi lido no tipo da mensagem.

S
ViniGodoy:
Já rodou com o depurador para ver quando a String ficou null?

Uma coisa, seu i provavelmente não irá começar em 0, e sim em 1. Isso porque um byte já foi lido no tipo da mensagem.

Fiz isso e ainda imprime null.
Tentei ir subtraindo os bytes, mas nao consegui , até que...
Somei as linhas do for, antes de dar null;.. Que são 14 e deu certo.

Mas nao estou entendendo o porque disso...

@Override
    public void run() {

        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
                             
            int tamanho = dis.readInt(); // Como é Read Int, acredito que ja leia 4 Bytes, correto?
            int tipoMensagem = dis.read(); // Tipo de mensagem
            
            System.out.println(tamanho);
            System.out.println(tipoMensagem);
            
            String input = &quot;!*&quot;;
            if (tipoMensagem == 0)// È uma Mensagem
            {
               
                //Troquei 'tamanho' por 14 e Funcionou
                for (int i = 1; i &lt; 14; i++) {
                    input = input + dis.readChar();
                    System.out.println(&quot;&quot; + input); // Esta linha imprime aos poucos, certinho.... Mas 
                }
                
                System.out.println(&quot;Total : &quot; + input); // Esta debaixo imprime null -.-
            }
            
            

        } catch (Exception e) {
            System.out.println(e.getMessage());
            //e.printStackTrace();
        }

    }
run:
Server Opened...
Client Connected : 127.0.0.1
29
0
!*O
!*Ol
!*Ola
!*Ola 
!*Ola B
!*Ola By
!*Ola Byt
!*Ola Byte
!*Ola ByteA
!*Ola ByteAr
!*Ola ByteArr
!*Ola ByteArra
!*Ola ByteArray
Total : !*Ola ByteArray
V

Ué? Onde está o null? Ali está escrito:
Total !*Olá ByteArray.

S

ViniGodoy:
Ué? Onde está o null? Ali está escrito:
Total !*Olá ByteArray.

Então, foi porque eu troquei a variável ‘tamanho’ do for, para 14;

Aí ele Faz certo.
Mas se eu colocar Tamanho ou Tamanho -5 , ele imprime null !!

V

Sua confusão também está no fato de um char conter 2 bytes, não um só.

Então no for, ao invés de i++, você vai fazer i+=2;

E note que vai ficar certinho. Seu tamanho começa com 29. O i vai de 1 até 29, pulando de 2 em 2, ou seja, vc vai ler (29-1=28/2 = 14 caracteres).

S

ViniGodoy:
Sua confusão também está no fato de um char conter 2 bytes, não um só.

Então no for, ao invés de i++, você vai fazer i+=2;

E note que vai ficar certinho. Seu tamanho começa com 29. O i vai de 1 até 29, pulando de 2 em 2, ou seja, vc vai ler (29-1=28/2 = 14 caracteres).

aff è verdade. ASCII

LOL como sou estúpido. Pior que fiquei aqui tentando achar a lógica… haha, que chatO isso.

Eu posso tambem fazer tamanho/2 ?

Ahh , i+=2 é a mesma coisa que i = i +2 , não é ?

Obrigadão VinY!

S
hahaha Agora Funcionou!!!
run:
Server Opened...
Client Connected : 127.0.0.1
29
0
Total : !*Ola ByteArray!

Pior que eu Dormi pensando no que eu estava errando no input !!

@Override
    public void run() {

        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
                             
            int tamanho = dis.readInt(); // Como é Read Int, acredito que ja leia 4 Bytes, correto?
            int tipoMensagem = dis.read(); // Tipo de mensagem
            
            System.out.println(tamanho);
            System.out.println(tipoMensagem);
            
            String input = "!*";
            if (tipoMensagem == 0)// È uma Mensagem
            {
               
                //Troquei 'tamanho' por 14 e Funcionou
                for (int i = 1; i <tamanho;i=i+2) {
                    input = input + dis.readChar();
                    //System.out.println("" + input); // Esta linha imprime aos poucos, certinho.... Mas 
                }
                
                System.out.println("Total : " + input); // Esta debaixo imprime null -.-
            }
            
            

        } catch (Exception e) {
            System.out.println(e.getMessage());
            //e.printStackTrace();
        }

    }
V

Então, com o tempo vc cria métodos utilitários para facilitar o trabalho. Eu, por exemplo, costumo a mandar um int com o tamanho da String antes de todas as Strings. Mas daí, já mando o tamanho em caracteres (o size() da String). Isso facilita muito a leitura. E já crio um método readString na minha classe para ler o int seguido dos chars e retornar a String direto:

public String readString(DataInputStream in) { int tamanho = in.nextInt(); StringBuilder out = new StringBuilder(tamanho); for (int i = 0; i &lt; tamanho; i++) { out.append(in.readChar()); } return out.toString(); }

Mas claro, isso porque em meus protocolos, eu sempre incluo o tamanho da String antes do texto. Outra possibilidade é fazer um método que leia até um terminador, por exemplo, o \0 (isso é útil se você estiver comunicando com C - onde no caso, cada caracter é ASCII e não unicode e só ocupa 1 byte):

public String readCString(DataInputStream in) { int tamanho = in.nextInt(); StringBuilder out = new StringBuilder(); char ch = (char)in.nextByte(); while (ch != '\0') { out.append(ch); ch = (char)in.nextByte(); } return out.toString(); }

S

ViniGodoy:
Então, com o tempo vc cria métodos utilitários para facilitar o trabalho. Eu, por exemplo, costumo a mandar um int com o tamanho da String antes de todas as Strings. Mas daí, já mando o tamanho em caracteres (o size() da String). Isso facilita muito a leitura. E já crio um método readString na minha classe para ler o int seguido dos chars e retornar a String direto:

public String readString(DataInputStream in) { int tamanho = in.nextInt(); StringBuilder out = new StringBuilder(tamanho); for (int i = 0; i &lt; tamanho; i++) { out.append(in.readChar()); } return out.toString(); }

Mas claro, isso porque em meus protocolos, eu sempre incluo o tamanho da String antes do texto. Outra possibilidade é fazer um método que leia até um terminador, por exemplo, o \0 (isso é útil se você estiver comunicando com C - onde no caso, cada caracter é ASCII e não unicode e só ocupa 1 byte):

public String readCString(DataInputStream in) { int tamanho = in.nextInt(); StringBuilder out = new StringBuilder(); char ch = (char)in.nextByte(); while (ch != '\0') { out.append(ch); ch = (char)in.nextByte(); } return out.toString(); }

Verdade, java usa unicode…
Mas achei que ascII também usava 8 bits - 2 bytes

Viny, posso tirar mais uma dúvida ??
Estou serializando o arrayList, mas eu devo enviar como Object Output ou byte Output???

// public void encodeAndSendUsersList(ArrayList<Usuarios> listUsers)

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Control;

import AuxManager.Usuarios;
import Manager.InitializeServer;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;
import java.io.Serializable;

/**
 *
 * @author André
 */
public class ServerMessenger implements Runnable {

    private Socket socket;
    public ArrayList&lt;Usuarios&gt; listaUsuarios;
    public InitializeServer main;

    public ServerMessenger(Socket s, InitializeServer m) {
        socket = s;
        main = m;

        Usuarios usuario = new Usuarios("" + socket.getInetAddress().getHostName(), socket, "" + socket.getInetAddress());
        main.listaUsuarios.add(usuario);

    }

    @Override
    public void run() {

        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());

            int tamanho = dis.readInt(); // Como é Read Int, acredito que ja leia 4 Bytes, correto?
            int tipoMensagem = dis.read(); // Tipo de mensagem

            System.out.println(tamanho);
            System.out.println(tipoMensagem);


            if (tipoMensagem == 0)// È uma Mensagem
            {
                String input = socket.getInetAddress() + "Said : ";
                for (int i = 1; i &lt; tamanho; i = i + 2) {
                    input = input + dis.readChar();
                    //System.out.println("" + input); 
                }
                decodeMessage(input);

            }



        } catch (Exception e) {
            System.out.println(e.getMessage());
            //e.printStackTrace();
        }

    }

    public void decodeMessage(String input) {
        try {

            //Devolve a Informação que o usuário digitou, para todos os clientes 
            for (int i = 0; i &lt; main.listaUsuarios.size(); i++) {
                Socket aux = main.listaUsuarios.get(i).getSocket();
                PrintWriter pwAux = new PrintWriter(aux.getOutputStream());

                pwAux.println(input);
                pwAux.flush();
            }//Fim da Devolução de Informação
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    public void encodeAndSendUsersList(ArrayList&lt;Usuarios&gt; listUsers) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            //DataOutputStream dos = new DataOutputStream(bos);
            //dos.writeByte(1);//1 == Array List!!!
            
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            oos.writeByte(1);
            oos.writeObject(listUsers);
            
            
            
            
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}
V

Eu sempre uso o DataOutputStream e DataInputStream para tudo. Dá mais trabalho, mas você tem mais controle sobre o protocolo. E, como você deve ter percebido, o protocolo é um fator bastante crítico em qualquer aplicação socket.

S

Hmm, mas ele nao tem Write(Object)

aa não ser que eu use toString();
Posso fazer isso ?

V

Você escreve campo por campo. E lê campo por campo…

S

Então em vez de eu mandar o array, eu mando as Strings que estao dentro do array?? Hmm, vou fazer isso

V
Isso. Vamos supor que você tenha um array de 10 Strings. Eu geralmente organizaria meu protocolo para enviar assim:

a) A quantidade de elementos do array (int)

Para cada String no array

b) O tamanho da String em caracteres (int)

c) O texto da String;

Assim fica fácil na hora de fazer a leitura.

S
<blockquote><div class="quote-author">ViniGodoy:</div>Isso. Vamos supor que você tenha um array de 10 Strings. Eu geralmente organizaria meu protocolo para enviar assim:

a) A quantidade de elementos do array (int)

Para cada String no array

b) O tamanho da String em caracteres (int)

c) O texto da String;

Assim fica fácil na hora de fazer a leitura.

Legal, agora consigo fazer !!
Só uma dúvida, na hora que eu lia os chars, eu lia 2 bytes/char

Agora pra ler, vou ter que fazer parse em , por exemplo, cada “,” , e em seguida guardo cada valor entre “,” em algum lugar, por exemplo em um outro array.

Consigo sim!, Vou fazer e ja posto aqui rsrsr

V

Em termos de código, esse exemplo ficaria:

Escrevendo:

out.writeInt(nomes.size()); for (String nome : nomes) { out.writeInt(nome.size()); out.writeChars(nome.toCharArray()); }

Lendo:

int tamanhoArray = in.readInt(); List&lt;String&gt; nomes = new ArrayList&lt;String&gt;(); for (int i = 0; i &lt; tamanhoArray; i++) { nomes.add(readString(in)); }

Sendo readString o método que descrevi no post anterior. :wink:

PS: Aquele writeInt e writeChars provavelmente eu transformaria num método chamado writeString.

V

Só confirmando: 1 byte = 8 bits.
1 char ascii = 1 byte - por isso existem 256 caracteres possíveis
1 char java = 2 bytes;

V

Observe que num protocolo binário não há separadores. Eu simplesmente escrevi as Strings e valores inteiros seguidos, um do lado do outro. Você organiza a escrita de modo a permitir a leitura posterior.

S

ViniGodoy:
Em termos de código, esse exemplo ficaria:

Escrevendo:

out.writeInt(nomes.size()); for (String nome : nomes) { out.writeInt(nome.size()); out.writeChars(nome.toCharArray()); }

Lendo:

int tamanhoArray = in.readInt(); List&lt;String&gt; nomes = new ArrayList&lt;String&gt;(); for (int i = 0; i &lt; tamanhoArray; i++) { nomes.add(readString(in)); }

Sendo readString o método que descrevi no post anterior. :wink:

PS: Aquele writeInt e writeChars provavelmente eu transformaria num método chamado writeString.

Mas ali no “for de leitura” voce nao re-calcula o tamanho da String do próximo nome do array;

Eu havia entendido assim :

Por exemplo :

ArrayList<String > lista = …

lista.add(“André”);
lista.add("Viny);

//

out.writeInt(5); // Só um exemplo! Mas 5 porque é A,N,D,R,E ( 5 letras)
out.writeChars(“André”);

out.WriteInt(4); // Porque sao 4 Letras : V I N Y
out.WriteChars(“Viny”);

//

Lógico que acima, teria um for com um método pra calcular o numero de letras…

Nesse caso o Array Teria o tamanho de cada Nome, e as Strings.
E antes eu iria colocar o tamanho do array todo…

hmm…

V

O que estou fazendo é enviar exatamente o que falei. O tamanho do array, o tamanho da String e o texto. No exemplo do seu list o envio seria:
O int 2, pois tem 2 elementos no array
5, pois é a quantidade de caracteres da palavra Andre
Os caracteres André
4, pois é a quantidade de caracteres da palavra Vini
Os caracteres Vini

Por isso, na leitura, o primeiro for vai de 0 até <2. E para cada a String, lê o tamanho e o texto (que é o que o método readString do post que citei faz).

Veja o método readString, do post anterior. Nele eu leio o int e os caracteres.

S

ViniGodoy:
O que estou fazendo é enviar exatamente o que falei. O tamanho do array, o tamanho da String e o texto. No exemplo do seu list o envio seria:
O int 2, pois tem 2 elementos no array
5, pois é a quantidade de caracteres da palavra Andre
Os caracteres André
4, pois é a quantidade de caracteres da palavra Vini
Os caracteres Vini

Por isso, na leitura, o primeiro for vai de 0 até <2. E para cada a String, lê o tamanho e o texto (que é o que o método readString do post que citei faz).

Veja o método readString, do post anterior. Nele eu leio o int e os caracteres.

Agora entendi!!!
Consigo fazer! xD

V

Aqui está o link do post onde eu defino o método readString:

S

[quote=ViniGodoy]Aqui está o link do post onde eu defino o método readString:

aa Obrigado :stuck_out_tongue:

Acabei de imprimir os dois agora.
Pena que eu tenho que passar pro Word primeiro…
Se eu mando imprimir a seleção , sai quase em miniatura no sulfite :smiley:

S
ViniGodoy:
Aqui está o link do post onde eu defino o método readString: http://www.guj.com.br/java/290210-duvidas-basicas-de-socket-/4#1536451

Viny, eu imprimi, rabisquei, rabisquei.
Rasurei...
Mas estou confuso na hora de ler os bytes.

A escrita eu fiz assim :

public void encodeAndSendArrayList(ArrayList&lt;Usuarios&gt; listUsers) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            DataOutputStream dos = new DataOutputStream(bos);

            dos.writeByte(1);//1 == Array List!!!
            dos.writeInt(listUsers.size());// Tamanho do Array List!!!

            for (int i = 0; i &lt; listUsers.size(); i++) {
                Usuarios aux = listUsers.get(i);

                dos.writeInt(aux.getNomeDeUsuario().length());
                dos.writeChars(aux.getNomeDeUsuario());

            }

            //
            byte[] msg = bos.toByteArray();
            int tamanhoDoArray = listUsers.size();
            
            for (int i = 0; i &lt; listUsers.size(); i++) {
                Socket auxSocket = listUsers.get(i).getSocket();
                DataOutputStream out = new DataOutputStream(auxSocket.getOutputStream());
                
                out.writeInt(tamanhoDoArray);
                out.write(msg);
                out.flush();
            }

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

Me da um empurrão de novo :D ???

S
Andre Lopes:
ViniGodoy:
Aqui está o link do post onde eu defino o método readString: http://www.guj.com.br/java/290210-duvidas-basicas-de-socket-/4#1536451

Viny, eu imprimi, rabisquei, rabisquei.
Rasurei...
Mas estou confuso na hora de ler os bytes.

A escrita eu fiz assim :

public void encodeAndSendArrayList(ArrayList&lt;Usuarios&gt; listUsers) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            DataOutputStream dos = new DataOutputStream(bos);

            dos.writeByte(1);//1 == Array List!!!
            dos.writeInt(listUsers.size());// Tamanho do Array List!!!

            for (int i = 0; i &lt; listUsers.size(); i++) {
                Usuarios aux = listUsers.get(i);

                dos.writeInt(aux.getNomeDeUsuario().length());
                dos.writeChars(aux.getNomeDeUsuario());

            }

            //
            byte[] msg = bos.toByteArray();
            int tamanhoDoArray = listUsers.size();
            
            for (int i = 0; i &lt; listUsers.size(); i++) {
                Socket auxSocket = listUsers.get(i).getSocket();
                DataOutputStream out = new DataOutputStream(auxSocket.getOutputStream());
                
                out.writeInt(tamanhoDoArray);
                out.write(msg);
                out.flush();
            }

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

Me da um empurrão de novo :D ???

OK, depois de algumas hora pensando....

-Se eu puder ler na ordem que eu escrevi, ao invés da ordem inversa...
Leio o 1 byte, que define que é um arrayList
Leio o int que vem após o byte, que define o tamanho.

--Leio o tamanho da primeira String
--Leio a String

Esta Correto Isto ?

--

Dúvidas extras :

Se o array estiver vazio... O tamanho deve vir 0, correto ?
Sobre Mac e PC, se eu tiver esse app rodando no mac, eu tenho que mudar o código?

Muito Obrigado
Guj Rules :D

S

OK, eu refiz todo o código do servidor e deixei os métodos e classes mais separados.

Agora assim, Enquanto eu escrevia esse post, eu pensei num problema.
Aquele ArrayList, eu nao posso enviar em forma de String, porque eu vou precisar enviar o socket pra que o cliente consiga enviar mensagens pra outros clientes.

Tem como eu escrever o byte de tamanho e o byte de tipoDeMensagem e enviar a lista serializada?

Eu gostei de organizar por Bytes, achei muito bacana.
Eu queria misturar os dois.

Como posso fazer isso?

V

Não se envia o socket. Um cliente manda para o servidor o nome (ou o id) de outro. O servidor vai então num hashmap, pega esse id, acha o socket do cliente em questão e então redireciona a mensagem para lá.

S

Ah ok.
Acabei de descobrir que nao posso serializar um socket.
Mas eu tinha feito certo rsrsr.

Vou fazer assim,
Vou criar um lista de forma que eu possa re-montar os sockets do lado do cliente.

V

O cliente geralmente só tem um socket, com o servidor. Não faz sentido abrir outros sockets.

O servidor vai possuir um socket para cada cliente conectado. Então as conversas sempre vão do cliente para o servidor, e do servidor para o outro cliente.

Se A quer falar com B, através de um servidor S, a conversa segue esse fluxo:
A->S->B

S

ViniGodoy:
O cliente geralmente só tem um socket, com o servidor. Não faz sentido abrir outros sockets.

O servidor vai possuir um socket para cada cliente conectado. Então as conversas sempre vão do cliente para o servidor, e do servidor para o outro cliente.

Se A quer falar com B, através de um servidor S, a conversa segue esse fluxo:
A->S->B

Verdade!
Não tinha pensado assim…
Muito bem, entao vou fazer a lista apenas com o nome dos usuarios!

Mas pelo menos agora entendi como empacotar um objeto dentro dos bytes e fazer os protocolos :smiley:

V

Esqueça essa história de ObjectStreams.
No fundo, ele não envia “o objeto” pela rede. Isso não existe. Ele simplesmente faz de forma automática o envio campo-a-campo do objeto, e remonta uma cópia desse objeto do outro lado da conexão.

Mas essa abordagem tem problemas. Você não tem controle sobre como essa serialiazação é feita. Não há garantias de que ela não vá mudar de uma versão de Java para outra. Então, se você serializar com um ObjectInputStream, nada garante que tua aplicação não vá dar pau pq o cliente resolveu atualizar a JRE dele do outro lado da linha.

Sempre que fizer uma aplicação com sockets tenha total controle sobre o protocolo de comunicação. Isso vai evitar muitas dores de cabeça. Se quiser deixar o código profissional, faça algumas mensagens de handshake, onde uma aplicação diz a outra que versão do protocolo está usando. Assim você poderia dar uma mensagem de erro elegante, caso um cliente muito antigo tente se conectar (ou desconectar sem crash caso alguém simplesmente jogue dados idiotas por sua conexão socket).

S
ViniGodoy:
Esqueça essa história de ObjectStreams. No fundo, ele não envia "o objeto" pela rede. Isso não existe. Ele simplesmente faz de forma automática o envio campo-a-campo do objeto, e remonta uma cópia desse objeto do outro lado da conexão.

Mas essa abordagem tem problemas. Você não tem controle sobre como essa serialiazação é feita. Não há garantias de que ela não vá mudar de uma versão de Java para outra. Então, se você serializar com um ObjectInputStream, nada garante que tua aplicação não vá dar pau pq o cliente resolveu atualizar a JRE dele do outro lado da linha.

Sempre que fizer uma aplicação com sockets tenha total controle sobre o protocolo de comunicação. Isso vai evitar muitas dores de cabeça. Se quiser deixar o código profissional, faça algumas mensagens de handshake, onde uma aplicação diz a outra que versão do protocolo está usando. Assim você poderia dar uma mensagem de erro elegante, caso um cliente muito antigo tente se conectar (ou desconectar sem crash caso alguém simplesmente jogue dados idiotas por sua conexão socket).

Tudo bem.

Fiz do jeito que voce me aconselhou.
O cliente recebe o tamanho da lista ( que é uma String ) mas nao consegue decodificar:

//Código do servidor :
public void sendListaUsuarios(ArrayList&lt;Usuarios&gt; listaUsuarios) {
        try {

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
             DataOutputStream dos = new DataOutputStream(bos);
              dos.writeByte(1);//Avisa que é uma lista de usuarios
            
            for (int i = 0; i &lt; listaUsuarios.size(); i++) 
            {
                Usuarios aux = listaUsuarios.get(i);
                //dos.writeInt(aux.getiNetAdress().length());
                dos.writeUTF(&quot;::&quot;);
                dos.writeUTF(&quot;&quot; + aux.getiNetAdress());
                
            }
             byte[] msg = bos.toByteArray();
             
             for(int i = 0;i&lt;listaUsuariosSockets.size();i++)
             {
                 UsuariosSockets aux = listaUsuariosSockets.get(i);
                 DataOutputStream out = new DataOutputStream(aux.getSocket().getOutputStream());
                 out.writeInt(msg.length);   System.out.println("\n/Server/Lista/Tamanho da mensagem Sendo Enviada : " + msg.length);
                 out.write(msg);
                 out.flush();
                 System.out.println("\nLista em Bytes Enviados para " + aux.getSocket().getInetAddress().getHostName());
             }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }

//Código do cliente :

@Override
    public void run() {
        try {
            while (true) {
              
                DataInputStream dis = new DataInputStream(socket.getInputStream());

                int tamanho = dis.readInt(); // Como é Read Int, acredito que ja leia 4 Bytes, correto?
                int tipoMensagem = dis.read(); // Tipo de mensagem

                System.out.println("Cliente*Tamanho DIS : " + tamanho);
                System.out.println("Cliente*TipoMensagem DIS : " + tipoMensagem);
                        
                if (tipoMensagem == 0) {
                    String input = "";
                    for (int i = 1; i &gt;&lt; tamanho; i = i + 2) {
                        input = input + dis.readChar();
                    }
                    System.out.println(&quot;&quot; + input);
                } else if (tipoMensagem == 1) {
                    System.out.println(&quot;È Um ArrayList! Decodificando ....&quot;);
                    String lista = &quot;&quot;;
                    
                    for(int i = 1; i &lt; tamanho; i ++)
                    {
                        lista = lista + dis.readUTF();
                    }
                   System.out.println(&quot;Lista : &quot; + lista);
                }

            }

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }


    }

O que estou fazendo de errado???

Obrigadão Viny !!

S

Até a linha System.out.println("È Um ArrayList! Decodificando ....");
Ele chega

Mas depois nao acontece nada ...

Eu tentei isso aqui agora :

} else if (tipoMensagem == 1) {
                    System.out.println("È Um ArrayList! Decodificando ....");
                    String lista = "";
                    
                    for(int i = 1; i < tamanho; i = i + 2)
                    {
                        lista = lista + dis.readUTF();
                    }
                   System.out.println("Lista : " + lista);
                }

            }

Nao foi.

S

OK, só atualizando o tópico..
Tive uma epifania quando fui no banheiro kkk

E fiz isso aqui quando voltei :

} else if (tipoMensagem == 1) {
                    System.out.println("È Um ArrayList! Decodificando ....");
                    String lista = "";
                    
                    for(int i = 1; i < tamanho; i = i + 1)
                    {
                        System.out.println("Array : " + lista);
                        lista = lista + dis.readUTF();
                    }
                   System.out.println("Lista : " + lista);
                }

Ele esta recebendo o array, mas o problema esta no tamanho.
Eu tentei i+2 mas nao deu certo

Como que devo usar esse readUTF() ?

Eu sei que o erro é do jeito que estou lendo..
Então pelo menos isso ja esta certo
:P

S

Consegui!!!

} else if (tipoMensagem == 1) {
                    System.out.println("È Um ArrayList! Decodificando ....");
                    String lista = "";
                    
                    for(int i = 0; i < tamanho; i = i + 1)
                    {
                        //System.out.println("Array -> " + dis.readUTF() + " -> Linha " + i);
                        lista = lista +"\n"+ dis.readUTF();
                    }
                   System.out.println(" Lista : " + lista);
                   System.out.println("Lista decodificada! Fim!");
                }
public void sendListaUsuarios(ArrayList<Usuarios> listaUsuarios) {
        try {

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
             DataOutputStream dos = new DataOutputStream(bos);
              dos.writeByte(1);//Avisa que é uma lista de usuarios
            
              int tamanho = listaUsuarios.size();
            for (int i = 0; i < tamanho; i++) 
            {
                Usuarios aux = listaUsuarios.get(i);
                
                dos.writeUTF("" + aux.getiNetAdress());
                
            }
             byte[] msg = bos.toByteArray();
             
             for(int i = 0;i<listaUsuariosSockets.size();i++)
             {
                 UsuariosSockets aux = listaUsuariosSockets.get(i);
                 DataOutputStream out = new DataOutputStream(aux.getSocket().getOutputStream());
                 out.writeInt(tamanho);   System.out.println("\n/Server/Lista/Tamanho da mensagem Sendo Enviada : " + msg.length + " Ou seja,lista.size() == " +tamanho);
                 out.write(msg);
                 out.flush();
                 System.out.println("\nLista em Bytes Enviados para " + aux.getSocket().getInetAddress().getHostName());
             }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }
S

aaa Viny.

Re-fiz os dois projetos.
O servidor e o cliente.

Mas ele só recebe uma mensagem e nao recebe a outra.

S

Será que se eu postar o link do 4shared com meus dois projetos é abusar ?
Não tenho mais pra quem pedir ajuda, colega meu esta viajando >.<
Mandei email pra ele com o link, mas duvido que ele vai responder logo haha

S

Só por Desencargo de consciencia


Ou Então :
http://www.4shared.com/archive/EpyyKX0O/Chat_Java_20.html

Quem sabe alguém baixa e me ajuda :smiley:

Criado 22 de dezembro de 2012
Ultima resposta 31 de dez. de 2012
Respostas 79
Participantes 4