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…
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() > 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
}
}
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 …
É, 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…
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)
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?
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.
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…
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