Sockets em java. Há Solução?

Bom dia pessoal,

Estou desenvolvendo uma aplicação em java que usa sockets, esta aplicação deve receber multiplas conexões, identifica-las e receber seus respectivos pacotes. Os pacotes que o aplicativo cliente envia é formado por 8 bytes, contudo o cliente pode enviar os 8 bytes de uma unica vez ou enviar pacotes quebrados tipo 2 bytes + 3 bytes + 3 bytes ou 3 bytes + 5 bytes.

Será que existe alguma maneira de garantir a recepção desse pacote por parte do aplicativo servidor em java ???

Como assim garantir a recepção dos pacotes???
Quem garante isso é o TCP.

Tu tem que ter uma logica para poder ler isso, mas se for toda essa comunicação no mesmo socket, dai fica facil… basta manter o buffer aberto e ler até que tenha chegado toda a informação…

Dica: Utiolize a API javax.nio para sockets, ele utiliza um conceito melhor para esta implementação…

nbluis,

vc fala fazer isso ??

in = socket.InputStream();

essa alternativa funciona bem para um cliente, mais se tiver por exemplo 20 ou 50 conectados ao servidor ??? no delphi consegui algo rezoavelmente bom, consigo indetificar as conexões e receber os pacotes quebrados com segurança, mais a aplicação vai rodar em linux não em windows.

A alternativa que estou pensado é usar threads, mais será que é seguro fazer isso ???

Uma alternativa para as Threads no caso de servidores de aplicações em rede com múltiplos clientes é o uso de Channels multiplexados.

Acho que esse pequeno exemplo deve servir:

import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;

public class Server {
   private static int port = 9999;
   public static void main(String args[])
     throws Exception {
     Selector selector = Selector.open();

     ServerSocketChannel channel =
       ServerSocketChannel.open();
     channel.configureBlocking(false);
     InetSocketAddress isa = new InetSocketAddress(port);
     channel.socket().bind(isa);

     // Register interest in when connection
     channel.register(selector, SelectionKey.OP_ACCEPT);

     // Wait for something of interest to happen
     while (selector.select() &gt 0) {
       // Get set of ready objects
       Set readyKeys = selector.selectedKeys();
       Iterator readyItor = readyKeys.iterator();

       // Walk through set
       while (readyItor.hasNext()) {

         // Get key from set
         SelectionKey key =
           (SelectionKey)readyItor.next();

         // Remove current entry
         readyItor.remove();

         if (key.isAcceptable()) {
           // Get channel
           ServerSocketChannel keyChannel =
             (ServerSocketChannel)key.channel();

           // Get server socket
           ServerSocket serverSocket = keyChannel.socket();

           // Accept request
           Socket socket = serverSocket.accept();

           // Return canned message
           PrintWriter out = new PrintWriter
             (socket.getOutputStream(), true);
           out.println("Hello, NIO");
           out.close();
         } else {
           System.err.println("Ooops");
         }

       }
     }
     // Never ends
   }
}

Inté

Cara, eu tenho trabalho muito em aplicações com sockets.

E todas elas são multithreads… tenho um bom retorno… sem problemas… sem contar que devem ser em média 5 clientes conectados simultaneamente o tempo todo… o servidor se vira bem …

valeu…

É, também trabalho mto com sockets, e o que fazemos é o seguinte:

instancio o ServerSocket e fico parado no accept. Quando meu servidor recebe uma conexão, o accept retorna um objeto socket. Passo esse objeto para uma outra thread para efeturar o processamento, e o meu servidor volta a escutar, independente do processamento da requisição.

Ou seja, recebo conexão, dou para outra classe processar e volto a escutar…

t+

rafael, tentei implementar da forma que comentou nesse código:

import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;


/**
 * Classe servidor para receber as conexões dos clientes
 */
public class Main implements Runnable {
    private int port;
    private ServerSocket serverSocket;
    private Socket socket;
    private InputStream in;
    private OutputStream out;
    private Thread currentThread;
    private byte[] buffRes = new byte[8];
    
    /** 
     * Método construtor da classe Main
     *
     * @param port identifica a porta de comunicação quer será usada pelo socket
     */
    public Main(int port) throws IOException {
        this.port = port;
        serverSocket = new ServerSocket(port);
        currentThread = new Thread(this);
        currentThread.start();        
    }
    
    /**
     * Método de execução implementado através da interface Runnable
     */
    public void run() {
        Thread thread = Thread.currentThread();
        while (currentThread == thread) {
            try {
                in = socket.getInputStream();
                /* Pega os pacotes enviados pela porta TCP/IP pela catraca */
                in.read(buffRes);
                /* Verifica o tamanho do pacote */
                if (buffRes.length >= 8) {
                    /* Processa o pacote enviado pelo cliente caso o mesmo
                       tenha 8 bytes.*/
                    //processCommand(buffRes);
                    System.out.println("Pacote recebido corretamente.");
                }
            } catch (IOException ex) {
                System.out.println(ex.getMessage().toString());
            } catch (Exception ex) {
                System.out.println(ex.getMessage().toString());
            }
        }
    }
    
    /** 
     * Método utilizado para para as threads em execução visto que o método
     * <code>stop()</code> esta deprecado.
     */
    public void stop() {
        currentThread = null;
    }
    
    /** Método main */
    public static void main(String[] args) {
        try {
            new Main(23);
        } catch (IOException ex) {
            System.out.println(ex.getMessage().toString());
        } catch (Exception ex) {
            System.out.println(ex.getMessage().toString());
        }
    }
    
}

só que agora tá dando o seguinte erro

Exception in thread “Thread-0” java.lang.NullPointerException
at javaapplication6.Main.run(Main.java:64)
at java.lang.Thread.run(Thread.java:595)

sabe o que pode ser ?

KWill esta solução com selector empilha as requisições e as trata tipo singlethread? Eu rodei este codigo em debug fazendo 5, 6 requisições e foi esta a impreção que eu tive! Este codigo ficaria bom para grande massa de acesso?

Dentro desse sue código, qual a linha 64?

A intenção desse código é tratar tudo com singlethread mesmo, evitando ter que criar múltiplas threads, numa tentativa de poupar a máquina.

Como usa NIO, acho que deve ser mais rápido e/ou gastar menos recursos de máquina, mas para ter certeza (ou quase…) só fazendo berchmarks para testar.

Inté.

Cara, não vejo ganho algum utilizando singleThread.

1 - Se tu tiver muitas conexões, um servidor SingleThread vai deixar tudo isso esperando… isso não é bom…

2 - Se tu tiver poucas Threads, não terá problema nenhum sobre processamento, threads não são tão custosas assim quanto a um servidor…

Minha Opinião…

Até…

Aproveitem para dar uma olhada neste artigo:

http://www.onjava.com/pub/a/onjava/2002/10/02/javanio.html?page=4

Deve ser esclarecedor para vocês, e não estou indicando a vocês que façam sempre monothread ou multithread, acho que é preciso dimensionar a solução de acordo com o tamanho do problema, no caso, o número de clientes conectados.

Inté.

pessoal, alguém saberia me dizer oq pode esta errado nesse código para o mesmo só funcionar qndo o cliente desconecta do servidor ??

    public void run() {
        Thread thread = Thread.currentThread();
        while (currentThread == thread) {
            try {
                in = socket.getInputStream();
                out = socket.getOutputStream();
                in.read(buffRes);
                processCommand(buffRes);
                out.write(buffRes);
                
            } catch (IOException ex) {
                System.out.println(ex.getMessage().toString());
            } catch (Exception ex) {
                System.out.println(ex.getMessage().toString());
            }
        }
    }

falta o flush();

Até…

e como uso o flush() no InputStream ??? não encontrei o metodo no netbeans

O Flush é no outputstream.

valeu…

[quote=destructor]e como uso o flush() no InputStream ??? não encontrei o metodo no netbeans
[/quote]

Você precisa usar flush() no OutputStream…

Inté.

Cara, não é bem assim que o ServerSocket funciona. Você tem que usar o método Accept() para pegar o socket propriamente dito. Experimente colocar esta linha embaixo de serverSocket = new ServerSocket(port)

this.socket = serverSocket.accept();

Esta linha fica esperendo algum cliente conectar. Quando conecta ela retorna o socket da conexão. O que se faz é colocar isso dentro de um while e cada vez que um cliente conecta vc inicia uma nova Thread para tratar dele.

Te recomendo esse caminho, a não ser que vc vai tenha milhares de clientes. Eu já implemtentei um servidor com NIO não bloqueante para economizar Threads e no fim só deu confusão… começa simples…

Aqui ta mais explicado: http://www.imasters.com.br/artigo/2385

então ciczan, o negocio é o seguinte. esse programa vai aceitar varias conexões, tipo 150 conexões certo dae estou tentando encontrar uma maneira de fazer isso, a unica que conheço em java é com threads mais estava fazendo um teste, exatamente isso que vc falou, e ele entra em loop despois que o cliente se desconecta.

estou quebrando a cabeça mesmo pra encontrar uma forma de fazer isso