Enviar Strings e objetos( como ArrayList por exemplo) por Socket

Pessoal, tenho uma comunicação cliente-servidor aqui feita em socket. Antes eu estava usando o objeto PrintStream encadeado a um buffer para o cliente ler mensagens do servidor e vice-versa, e o objeto PrintStream para escrever no fluxo do socket. Eu enviava apenas mensagens( String ) e não tinha problema nenhum em ler. Agora eu estou precisando enviar um ArrayList para o cliente, e o cliente precisa ler esse arrayList, como posso fazer isso? Com qual objeto e como posso identificar se é uma String que ele leu ou um objeto diferente?

Obrigado espero ter sido claro.

Pra enviar qualquer coisa através do socket essa “coisa” precisa implementar a interface Serializable. Como a String implementa, você conseguiu mandar numa boa.
O ArrayList também implementa, porém os objetos que estão dentro dele precisam implementar a interface da mesma forma.

Tenta enviar com ObjectOutputStream e ler com ObjectInputStream. Qualquer coisa posta o código.

Isso :slight_smile:

[quote=leandronsp]Pra enviar qualquer coisa através do socket essa “coisa” precisa implementar a interface Serializable. Como a String implementa, você conseguiu mandar numa boa.
O ArrayList também implementa, porém os objetos que estão dentro dele precisam implementar a interface da mesma forma.

Tenta enviar com ObjectOutputStream e ler com ObjectInputStream. Qualquer coisa posta o código.[/quote]

Mais ai é que está, como eu vou saber se está vindo uma String ou um ArrayList na hora que eu der um ObjectInputStream.readObject(); ?

Se você deixar em métodos diferentes, e já “sabendo” o que vai vir, pode usar o cast.
Acho que o instance of também resolve neste caso.

ObjectInputStream está entre as maiores furadas quando o assunto é comunicação via socket.

O ideal é aprender a fazer direito, a começar por organizar seu protocolo:

Ou procurar APIs específicas para serialização via rede.

[quote=leandronsp]Se você deixar em métodos diferentes, e já “sabendo” o que vai vir, pode usar o cast.
Acho que o instance of também resolve neste caso.
[/quote]

No momento não vejo alternativa deixando em método diferente. Pensei em usar instance of uma hora também mas nao consegui implementar, vou dar uma olhada no link que o vini passou e posto qualquer coisa aqui.

[quote=ViniGodoy]ObjectInputStream está entre as maiores furadas quando o assunto é comunicação via socket.

O ideal é aprender a fazer direito, a começar por organizar seu protocolo:

Ou procurar APIs específicas para serialização via rede. [/quote]
Muito melhor organizando o próprio protocolo mesmo!

[quote=leandronsp]Pra enviar qualquer coisa através do socket essa “coisa” precisa implementar a interface Serializable. Como a String implementa, você conseguiu mandar numa boa.
O ArrayList também implementa, porém os objetos que estão dentro dele precisam implementar a interface da mesma forma.

Tenta enviar com ObjectOutputStream e ler com ObjectInputStream. Qualquer coisa posta o código.[/quote]

Concordo com nosso amigo moderador…

Mas se vc estiver usando o ObjectOutputStream e quiser identificar o objeto… desserializa ele em um Object e depois de um instanceof para saber se é uma String ou um array… Lembre-se que String também é Object

Vou tentar dos dois jeitos para ver como que fica e ViniGodoy se eu tiver alguma dúvida em relação a criar o protocolo, crio um tópico novo ou posto lá mesmo?

Não consegui entender a parte de criar um protocolo no tópico que o ViniGodoy passou.

O que você não entendeu?

O que você não entendeu?[/quote]

Como eu poderia implementar aquele exemplo a minha situação, onde é preciso enviar uma string e um arrayList em certos momentos. É porque é assim. É um servidor multithread. O cliente se conecta ao servidor e envia uma mensagem passando o seu nome de usuario logo que se conecta. O servidor cria uma thread assim que recebe a conexão para escutar por mensagens do cliente, e escuta a mensagem com o nome do usuario e armazena em um ArrayList de String e em um map com a chave sendo o nome do usuario e o valor sendo o fluxo de saida do usuario. Depois eu tenho que enviar esse arrayList de volta para o cliente, conforme mais clientes vão se conectando, para ele ter a relação dos usuarios que estão online. É mais ou menos isso.

Da mesma forma que explique lá.

Você deve organizar suas mensagens de modo a conter:
a) O tamanho da mensagem;
b) Um código, indicando o tipo da mensagem;
c) Os dados da mensagem.

Então, seu cliente não vai mais só mandar uma String. E sim, um int indicando o tamanho da mensagem. Um int com o código. Se o código for, por exemplo, 1, indica que é a String do nome que virá nos dados. Se for 2, pode indicar que é o array list.

No caso da mensagem 2, você poderia enviar:
a) Quantos elementos estão no arrayList;
b) O tamanho da String do primeiro elemento;
c) A String.
d) O tamanho do segundo
e) … e assim por diante.

Organizar o protocolo é justamente parar um tempo e pensar em que mensagens o seu sistema vai ter, e que dados essas mensagens conterão. Com isso em mãos, você saberá exatamente como enviar e como receber toda informação que você tem para trafegar.

[quote=ViniGodoy]Da mesma forma que explique lá.

Você deve organizar suas mensagens de modo a conter:
a) O tamanho da mensagem;
b) Um código, indicando o tipo da mensagem;
c) Os dados da mensagem.

Então, seu cliente não vai mais só mandar uma String. E sim, um int indicando o tamanho da mensagem. Um int com o código. Se o código for, por exemplo, 1, indica que é a String do nome que virá nos dados. Se for 2, pode indicar que é o array list.

No caso da mensagem 2, você poderia enviar:
a) Quantos elementos estão no arrayList;
b) O tamanho da String do primeiro elemento;
c) A String.
d) O tamanho do segundo
e) … e assim por diante.

Organizar o protocolo é justamente parar um tempo e pensar em que mensagens o seu sistema vai ter, e que dados essas mensagens conterão. Com isso em mãos, você saberá exatamente como enviar e como receber toda informação que você tem para trafegar.[/quote]

E quais objetos de fluxo eu usarei para enviar e para receber?

Eu usaria o DataInputStream e o DataOutputStream. Eles não são tão automágicos, mas te dão total controle.
E, no caso de fazer comunicações, é importante ter controle.

Protocolo é uma coisa muito boboca, se você pensar bem.

É você que está se embananando todo e achando que é uma coisa de 7 cabeças.

Uma forma bem simples de organizar um protocolo é você criar uma coleção de códigos (podem ser numéricos, por exemplo) para as perguntas e para as respostas desejadas.

Digamos que uma pergunta tenha 2 tipos de respostas, uma que é uma String, e outra que é uma lista de Strings.

Você pode indicar que a resposta do tipo 1 é uma String isolada, e a resposta do tipo 2 é uma lista de Strings.

Você pode até ter subcódigos - por exemplo, no caso da resposta do tipo 2, você pega mais um código, que é a quantidade de strings nessa lista.

Ou seja, nada como um pedaço de papel e lápis. Eu vejo que muita gente se embanana todo porque não consegue pôr suas idéias no papel e fica direto tentando um monte de coisas no computador. Que tal fazer alguns diagramas, hein?

[quote=ViniGodoy]Eu usaria o DataInputStream e o DataOutputStream. Eles não são tão automágicos, mas te dão total controle.
E, no caso de fazer comunicações, é importante ter controle.[/quote]

No javadoc do DataInputStream ou do Output diz que não é seguro para multithread. E o servidor é multithread, não teria problema?

Vocês dois poderiam me ajudar então? Vou colocando aqui o meu protocolo e vocês a medida do possível vão dizendo o que está errado, faltando, etc?

Praticamente nenhum stream é.

Ele só quer dizer que duas threads não podem acessar o mesmo stream ao mesmo tempo. Mas cada cliente terá seu próprio stream, então, não há acesso multi-thread sobre o stream em si.