Socket!

ServidorSocket1 <–> Client1
ServidorSocket1 <–> Client2
ServidorSocket1 <–> Client3
ServidorSocket1 <–> Client4
ServidorSocket1 <–> Client5
ServidorSocket1 <–> Client6

Situação 1 - Permitir mais de uma conexão(Client) simultâneamente;

Situação 2 - Identificar cada Client no Servidor e enviar dados exclusivamente para ele.

Duvidas: Consigo fazer isso utilizando a mesma porta?

           Como identificar cada um dos clientes no servidor?

Alguem pode me ajudar?

Obrigado

A classe ServerSocket escuta em uma única porta.

Cada socket que se conecta, gera um novo objeto Socket diferente. Esse objeto deve ser submetido a thread que irá monitorar sua comunicação.

Sendo assim meu metodo accept() que me retorna um soket dve ficar dentro do meu while(true)??? e devo montar algo como um Array de sockets? seria mais ou menos isso?

Seria exatamente isso.

Você terá um while nesses moldes.

[code]while (isServerRunning) {

Socket client = server.accept();

ClientHandlerRunnable handler = new ClientHandlerRunnable(client);
conectedClientes.add(client);
Thread clientThread = new Thread(handler);
clientThread.setDaemon(true);
clientThread.start();

}[/code]

Tentei fazer o que disse, mas continua dando erro…na verdade estou com dificuldade em armazenar os clientes e criar os seus BufferedReader e PrintStream

veja o codigo do meu server…valeu.


import java.net.*;
 import java.io.*;
 
 public class SocketServer implements Runnable
 {
      ServerSocket ss;
 
         public SocketServer(int porta) throws Exception{
           ss = new ServerSocket(porta);
 
           new Thread(this).start();
 
           System.out.println("Servidor ouvindo na porta:" + porta);
 
         }
 
      public void run(){
           try{
                while(true){
                     new TrataCliente(ss.accept()).start();
                     System.out.println("Cliente atendido!");
 
                }
 
           }catch(Exception e){
                e.printStackTrace();
                System.exit(1);
           }
      }
     
 }
 

 class TrataCliente extends Thread
 {
      private Socket client;
 
      public TrataCliente(Socket s){
           client = s;
      }
 
      public void run(){
           try{
                // aqui vai a sua comunicacao com o cliente
                ObjectInputStream oi = new ObjectInputStream(client.getInputStream());
 
                System.out.println("Chegou do cliente:" + oi.readObject());
 
                client.close();
}
           catch(Exception e){
                e.printStackTrace();
                System.exit(1);
           }
      }
 }

Erro: init:
deps-jar:
Compiling 2 source files to C:\Users\ti_rodolfo\Desktop\Socket (MultiClients)\SocketMultiClients\build\classes
compile:
run:
Servidor ouvindo na porta:1099
Cliente atendido!
java.io.StreamCorruptedException: invalid stream header
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:764)
at java.io.ObjectInputStream.(ObjectInputStream.java:277)
at socketmulticlients.TrataCliente.run(SocketServer.java:56)
Java Result: 1
EXECUTADO COM SUCESSO (tempo total: 22 segundos)

Esse problema está relacionado ao ObjectInputStream e ao ObjectOutputStream, não ao socket propriamente dito.

Entao cara mudei minha estrutura agora esta tudo diferente…

Estou conseguindo conectar mais do que um client mas nao consigo identificar quem e quem…veja ficouate mais curto o codigo!!!




import java.net.*;
 import java.io.*;

 public class SocketServer implements Runnable
 {
      ServerSocket ss;

         public SocketServer(int porta) throws Exception{
           ss = new ServerSocket(porta);

           new Thread(this).start();

           System.out.println("Servidor ouvindo na porta:" + porta);

         }

      public void run(){
           try{
                while(true){
                     new TrataCliente(ss.accept()).start();
                     System.out.println("Cliente atendido!");

                }

           }catch(Exception e){
                e.printStackTrace();
                System.exit(1);
           }
      }
       public static void main(String[] args){
	             try{
	                  new SocketServer(1000);

	             }catch(Exception e){
	                  e.printStackTrace();
	                  System.exit(1);
	             }
	        }


 }


 class TrataCliente extends Thread
 {
      private Socket client;

      public TrataCliente(Socket s){
           client = s;
      }

      public void run(){
           try{
                // aqui vai a sua comunicacao com o cliente
              PrintWriter out = new PrintWriter(client.getOutputStream(), true);
              BufferedReader  in =  new BufferedReader(new InputStreamReader(client.getInputStream()));
              while(true){
	String x =   in.readLine();
                System.out.println("Valor do Tag...:" + x);
                out.println(x);

               }
}
           catch(Exception e){
                e.printStackTrace();
                System.exit(1);
           }
      }
 }

Legal. O que você quer dizer com “identificar quem é quem?”

Que tipo de identificação você precisa?

Bom vamos por partes pois e a primeira vez que trabalho com Thread e Socket entao ja viu ne? to lascado…kkkk

1º Conectar mais do que um cliente no servidor – CONCLUIDO

2º Saber quem e cada Cliente ex:

Algum cliente se conectou e fez uma requisição ao servidor como o servidor ira saber quem e esse cliente e como responder exatamente a ele, caso 3 clients se conectarem como vou saber quem e o 1 quem e o 2 e quem e o 3 e caso eu queira mandar uma mensagem somente ao 2 com o faço?

Obs: O meu codigo esta indo pelo camiho certo seria mais ou menos isso que eu fiz?
Valeu cara

Teu código tá no caminho, sim! :slight_smile:

Vamos as suas perguntas:

  1. Algum cliente se conectou e fez uma requisição ao servidor como o servidor ira saber quem e esse cliente e como responder exatamente a ele?
    Simples, apenas o socket do cliente vai enviar a requisição. Ela chegará só pelo stream de quem fez a requisição. O runnable que cuida desse stream cliente cuida de processar o que chegou e responder o cliente.

  2. Caso 3 clients se conectarem como vou saber quem e o 1 quem e o 2 e quem e o 3 e caso eu queira mandar uma mensagem somente ao 2 com o faço?

Você usa o socket do segundo para mandar a mensagem só para o segundo. Lembre-se cada client tem seu próprio objeto socket.

Por isso é uma boa guardar os runnables que controlam os sockets num list. Assim, o índice da lista diferencia quem é quem e no Runnable você põe as devidas sincronizações de um código multi-thread. Fica fácil também o servidor fazer um “broadcast” de alguma mensagem, basta percorrer a lista e notificar todos os runnables. Sacou?

Etao estou entendendo por partes vou tentar implementar o Array necessario agradeço a sua ajuda, e jaja eu volto em num some nao kkkkkk valeu mesmo em vini vou dar uma acelerada aqui e ver o que consigo fazer.

Cara eu estou meio perdido nao estou conseguindo entender em exato o que devo colocar dentro do meu array…seriam os sockets? desculpe ficar fazendo varias perguntas mas e que eu so novato na parada…valeu.

Eu colocaria os Runnables, que monitoram os streams dos sockets. Não os sockets diretamente.
No seu caso, você implementou tudo como filho da classe thread. Então põe esse filho mesmo.

Eu prefiro sempre implementar o Runnable a parte. Você pode chamado de SocketController ou qualquer coisa parecida. Ponha neles métodos para enviar mensagens para o socket. Dependendo da aplicação que você estiver fazendo, também é interessante transformar os dados que vem do socket em eventos (no meu caso foi uma ótima).

Boa Tarde Vini…

Estou apanhando muito mas estou conseguindo andar, nossa como e complicado esse esquema de Threads ne? Vamos para as duvidas…

Cara eu coloquei dentro de um vetor as minhas Runnables que cuidam do meu socket, so que o que eu necessito, vamos supor que tenho 4 clients conectados, Maria, Joana, Mario e Jose e Maria conversa apenas com Mario e Joana apenas com Jose isso e possivel, por exemplo Maria e Mario nao conseguem ver o que Joana e Jose estao conversando e vice versa?

Valeu…

É possível.

Mas seu problema não são mais as threads, e sim, em criar um protocolo.

Agora você que você consegue saber que clientes estão conectados e armazenar um índice para eles, é hora de sentar e pensar em como será a comunicação com esses clientes.

Defina as mensagens que o servidor enviará para os clientes e vice-versa. Por exemplo, essa seria uma possível troca de mensagens do cliente na hora da conexão:

Cliente conecta no servidor. Envia então:
1 string dizendo o seu nome

O servidor responde
1 byte com identificador da mensagem (conexão OK)
1 int dizendo o ID de cliente
1 int dizendo quantos bytes tem o nome de um cliente conectado
A string com o nome do cliente
(e esses dois últimos dados, o tam e o nome, se repetem até que o tamanho seja = 0)

O servidor envia aos demais clientes
1 byte com o identificador da mensagem (novo cliente conectado)
1 int com o tamanho do string do nome do cliente
O string com o nome do cliente
1 int com o ID desse cliente

O cliente quer se comunicar com outro cliente, em particular, ele envia:
1 byte com o identificador da mensagem (comunicar somente com)
1 int com o ID do cliente
1 int com o tamanho da mensagem
String com a mensagem.

E assim por diante. Ao invés de um array de clientes, será melhor ter um MAP do ID do cliente para seu Socket. Quando o servidor recebe uma mensagem (como a mensagem de “comunicar somente com”) ele decodifica, localiza o cliente nesse map que deve receber a mensagem, e envia só para eles. Defina mensagens para tudo mais que você quiser fazer (desconectar do servidor, mensagem pública, etc).

Curiosidade: Esse seu protocolo é chamado protocolo de aplicação e localiza-se na sétima camada do TCP/IP. Outros protocolos assim são o FTP, HTTP, etc.

Outra dica: Ao invés de bytes brutos para lá e para cá, pode ser uma boa idéia passar só um textão com um XML. É menos econômico, mas dependendo do tamanho do seu protocolo, pode ser mais fácil usar o próprio DOM para parsear a mensagem. Se for um trabalho de faculdade, ou só uma aplicação “de brinquedo”, eu faria usando os bytes diretamente.

Cara agradeço muito a sua força, vou tentar em cima do que me disse bolar algo que se enquadre com o que necessito…valeu mesmo

E um aplicação real cara preciso desenvolver isso logo pois querem concluir isso no maximo ate meio de dezembro…

Valeeeeeewww

Se isso não for um trabalho de faculdade, dê uma pesquisada sobre RMI.
Com RMI, o Java faz a parte da rede para você… e você só chama métodos, como se estivessem todas as aplicações na mesma VM…

Entao ja tentei fazer tudo isso com RMI que seria execução de metodos remotamente ne? Mas o que pega e que temos uma aplicação aqui que so pode rodar com jdk 1.3 (vovó essa em) e o RMI se eu nao me engano e so a partir da 1.4 cara isso ta dando uma dor de cabeça mas eu acho que ja encontrei a solução, ou seja fiz uma POG …kkkkk…cara obrigado vc me ajudou muito…valeu mesmo.

Vini vc falou que seria uma boa transformar as mensagens que vem do client em eventos, uma otima ideia seria exatamente o que eu preciso, pode me ajudar?