Saltar para conteúdo


Foto
- - - - -

Servidor Tcp Nio Com Selector


  • Por favor inicie sessão para responder
10 respostas a este tópico

#1 renna

renna

    Membro

  • Membros
  • PipPip
  • 106 mensagens
  • Zte Blade (San Francisco), Galaxy Note II

Mensagem publicada 16 July 2012 - 22:47

Boas,


Estou a desenvolver uma app android que erá ser um servidor, ou seja, tenho a app a correr num tablet e depois outros tablets irão-se ligar a ele. Eu estou a utilizar o NIO do java com um selector, para poupar no uso das threads. Mas o problema é, eu tenho o selector feito e a correr numa aplicação java mesmo, mas quando o coloco no android, simplesmente não acontece nada, é como que se não estivesse a correr nada na determinada porta.


Quando tento ligar com uma app qualquer dá Connection Refused.


Já tenho a permissão da Internet.


Codigo java com o selector:


[font=Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif][size=4][left][background=rgb(255, 255, 255)]
Thread t = new Thread(new Runnable() {[/background][/left][/size][/font]
    private Selector		    selector;
    private ServerSocketChannel sChan;
    private List<SocketChannel> sockets;
    public void run() {
	    try {
		    selector = SelectorProvider.provider().openSelector();
		    sChan = ServerSocketChannel.open();
		    InetSocketAddress iaddr = new InetSocketAddress(InetAddress.getLocalHost(), 8000);
		    sChan.configureBlocking(false);
		    sChan.socket().bind(iaddr);
		    System.out.println("Running on port:" + sChan.socket().getLocalPort());
		    sChan.register(selector, SelectionKey.OP_ACCEPT);
		    sockets = new LinkedList<SocketChannel>();
	    }
	    catch (IOException e) {
		    e.printStackTrace();
	    }
	    Iterator<SelectionKey> it;
	    try {
		    while (true) {
			    selector.select();
			    it = selector.selectedKeys().iterator();
			    while (it.hasNext()) {
				    SelectionKey key = it.next();
				    it.remove();
				    if (!key.isValid()) {
					    continue;
				    }
				    // Finish connection in case of an error
				    if (key.isConnectable()) {
					    SocketChannel ssc = (SocketChannel) key.channel();
					    if (ssc.isConnectionPending()) {
						    ssc.finishConnect();
					    }
				    }
				    if (key.isAcceptable()) {
					    ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
					    SocketChannel newClient = ssc.accept();
					    newClient.configureBlocking(false);
					    newClient.register(selector, SelectionKey.OP_READ);
					    sockets.add(newClient);
					    System.out.println("new client: " + newClient.socket().getInetAddress().getHostAddress());
				    }
				    if (key.isReadable()) {
					    SocketChannel sc = (SocketChannel) key.channel();
					    ByteBuffer data = ByteBuffer.allocate(sc.socket().getSendBufferSize());
					    System.out.println("new message: " + sc.socket().getInetAddress().getHostAddress());
					    if (sc.read(data) == -1) {
						    continue;
					    }
					    data.flip();
					    Teste m = (Teste) UdpUtil.byteToMessage(data.array());
					    System.out.println("message: " + m);
					    System.out.println("\n\n" + m.cenas);
					    sc.close();
				    }
			    }
		    }
	    }
	    catch (IOException e) {
		    e.printStackTrace();
	    }
    }
});
t.start();
Codigo Cliente:
InetSocketAddress isa = new InetSocketAddress(InetAddress.getByName("192.168.2.102"), 8000);
    SocketChannel sc = null;
    try {
	    // Connect
	    sc = SocketChannel.open();
	    sc.connect(isa);
	    // Read the time from the remote host. For simplicity we assume
	    // that the time comes back to us in a single packet, so that we
	    // only need to read once.
	    byte[] message = UdpUtil.messageToByteMessage(new messages.Teste("hello there"));
	    ByteBuffer buf = ByteBuffer.wrap(message);
	    sc.write(buf);
    }
    finally {
	    // Make sure we close the channel (and hence the socket)
	    if (sc != null) {
		    sc.close();
	    }
}
Já testei até com este codigo: http://systembash.co...and-tcp-client/ e funcionou bem, agora com um selector não funciona .
Obrigado desde já ;)

#2 r3pek

r3pek

    Guru de Android

  • Former Staff
  • PipPipPipPipPip
  • 1560 mensagens
  • LocalizaçãoBA4 - Terceira - Açores
  • Nexus One + Motorola XOOM

Mensagem publicada 16 July 2012 - 23:23

podes mostrar o logcat do "servidor"?

#3 pedronveloso

pedronveloso

    Veloso

  • Administradores
  • 1578 mensagens
  • S8

Mensagem publicada 16 July 2012 - 23:26

Não sei ao olhar para aí o que poderá estar mal, até porque nunca usei Selectors e é um conceito que estou pouco familiarizado. No entanto posso-te já aconselhar a que não faças System.out mas sim faças uso da class Log de Android que é class que se deve usar para falar com o logcat do adb' class='bbc_url' title='Link Externo' rel='nofollow external'>http://www.androidpt.info/index.php?title=ADB']adb, e nessa sim podes especificar a tag e grau de aviso do log, tirando uma linha das que estás a fazer uso ficaria deste género:

Log.v("app_java_nio","Running on port:" + sChan.socket().getLocalPort());


#4 renna

renna

    Membro

  • Membros
  • PipPip
  • 106 mensagens
  • Zte Blade (San Francisco), Galaxy Note II

Mensagem publicada 16 July 2012 - 23:26

No servidor não acontece nada, o selector simplesmente não acorda.
Apenas no cliente dá connection refused

#5 renna

renna

    Membro

  • Membros
  • PipPip
  • 106 mensagens
  • Zte Blade (San Francisco), Galaxy Note II

Mensagem publicada 16 July 2012 - 23:28

Não sei ao olhar para aí o que poderá estar mal, até porque nunca usei Selectors e é um conceito que estou pouco familiarizado. No entanto posso-te já aconselhar a que não faças System.out mas sim faças uso da class Log de Android que é class que se deve usar para falar com o logcat do [acrlink='http://www.androidpt...39;adb[/acrlink] e nessa sim podes especificar a tag e grau de aviso do log, tirando uma linha das que estás a fazer uso ficaria deste género:

Log.v("app_java_nio","Running on port:" + sChan.socket().getLocalPort());

Sim eu conheço a class log ;) eu normalmente uso-a sempre
só por vezes é que uso o System.out para não ter que meter sempre a tag (preguiça :P), mas de qualquer das formas o System.out no android também imprime para o logcat
E também como estava a correr isto num programa java mesmo, o Log.d não funciona.

Editado por renna, 16 July 2012 - 23:34.


#6 pedronveloso

pedronveloso

    Veloso

  • Administradores
  • 1578 mensagens
  • S8

Mensagem publicada 16 July 2012 - 23:35

Sim eu conheço a class log ;) eu normalmente uso-a sempre
só por vezes uso o System.out para não ter que meter sempre a tag (preguiça :P)


Eu uso a Tag numa constant para não cair no erro de escrever diferente ;).

Quanto ao erro, repliquei o código aqui e consigo perceber que acontece nesta linha:

sc.connect(isa);

e o output do erro é algo deste género:

07-17 00:26:48.952: WARN/System.err(4373): java.net.ConnectException: Connection refused
07-17 00:26:48.952: WARN/System.err(4373): at org.apache.harmony.luni.platform.OSNetworkSystem.connect(Native Method)
07-17 00:26:48.952: WARN/System.err(4373): at dalvik.system.BlockGuard$WrappedNetworkSystem.connect(BlockGuard.java:357)
07-17 00:26:48.952: WARN/System.err(4373): at org.apache.harmony.nio.internal.SocketChannelImpl.connect(SocketChannelImpl.java:197)
07-17 00:26:48.952: WARN/System.err(4373): at com.pedronveloso.testejavanio.MainActivity.onCreate(MainActivity.java:93)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1722)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.ActivityThread.access$1500(ActivityThread.java:123)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
07-17 00:26:48.952: WARN/System.err(4373): at android.os.Handler.dispatchMessage(Handler.java:99)
07-17 00:26:48.952: WARN/System.err(4373): at android.os.Looper.loop(Looper.java:130)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.ActivityThread.main(ActivityThread.java:3835)
07-17 00:26:48.952: WARN/System.err(4373): at java.lang.reflect.Method.invokeNative(Native Method)
07-17 00:26:48.952: WARN/System.err(4373): at java.lang.reflect.Method.invoke(Method.java:507)
07-17 00:26:48.952: WARN/System.err(4373): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
07-17 00:26:48.952: WARN/System.err(4373): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
07-17 00:26:48.952: WARN/System.err(4373): at dalvik.system.NativeStart.main(Native Method)

Fiz-lo na tentativa de tentar perceber o flow do código, mas tal como disse nunca mexi com estas classes do Java NIO e portanto não sei assim de repente perceber o que se passa de errado, com este log talvez mais alguém te consiga ajudar ;).

#7 renna

renna

    Membro

  • Membros
  • PipPip
  • 106 mensagens
  • Zte Blade (San Francisco), Galaxy Note II

Mensagem publicada 16 July 2012 - 23:40


07-17 00:26:48.952: WARN/System.err(4373): java.net.ConnectException: Connection refused
07-17 00:26:48.952: WARN/System.err(4373): at org.apache.harmony.luni.platform.OSNetworkSystem.connect(Native Method)
07-17 00:26:48.952: WARN/System.err(4373): at dalvik.system.BlockGuard$WrappedNetworkSystem.connect(BlockGuard.java:357)
07-17 00:26:48.952: WARN/System.err(4373): at org.apache.harmony.nio.internal.SocketChannelImpl.connect(SocketChannelImpl.java:197)
07-17 00:26:48.952: WARN/System.err(4373): at com.pedronveloso.testejavanio.MainActivity.onCreate(MainActivity.java:93)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1722)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.ActivityThread.access$1500(ActivityThread.java:123)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
07-17 00:26:48.952: WARN/System.err(4373): at android.os.Handler.dispatchMessage(Handler.java:99)
07-17 00:26:48.952: WARN/System.err(4373): at android.os.Looper.loop(Looper.java:130)
07-17 00:26:48.952: WARN/System.err(4373): at android.app.ActivityThread.main(ActivityThread.java:3835)
07-17 00:26:48.952: WARN/System.err(4373): at java.lang.reflect.Method.invokeNative(Native Method)
07-17 00:26:48.952: WARN/System.err(4373): at java.lang.reflect.Method.invoke(Method.java:507)
07-17 00:26:48.952: WARN/System.err(4373): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
07-17 00:26:48.952: WARN/System.err(4373): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
07-17 00:26:48.952: WARN/System.err(4373): at dalvik.system.NativeStart.main(Native Method)

Fiz-lo na tentativa de tentar perceber o flow do código, mas tal como disse nunca mexi com estas classes do Java NIO e portanto não sei assim de repente perceber o que se passa de errado, com este log talvez mais alguém te consiga ajudar ;).

Sim isso é o que me dá do lado do cliente, parece que o ServerSocketChannel não está activo de alguma forma. Mas do lado do server não se passa nada.
Mas o que acho esquisito é isto funcionar em java e em android não

Editado por renna, 16 July 2012 - 23:40.


#8 pedronveloso

pedronveloso

    Veloso

  • Administradores
  • 1578 mensagens
  • S8

Mensagem publicada 16 July 2012 - 23:44

Pode ser que não tenha nada a ver (não vi a documentação ptt é tipo a mandar um tiro para o ar), mas em:

InetSocketAddress iaddr = new InetSocketAddress(InetAddress.getLocalHost(), 8000);

não tens de colocar o IP do servidor para ele aceitar conexões na rede e não apenas no localhost?

#9 r3pek

r3pek

    Guru de Android

  • Former Staff
  • PipPipPipPipPip
  • 1560 mensagens
  • LocalizaçãoBA4 - Terceira - Açores
  • Nexus One + Motorola XOOM

Mensagem publicada 17 July 2012 - 00:16

ou mesmo o "0.0.0.0"

#10 renna

renna

    Membro

  • Membros
  • PipPip
  • 106 mensagens
  • Zte Blade (San Francisco), Galaxy Note II

Mensagem publicada 17 July 2012 - 16:44

Pode ser que não tenha nada a ver (não vi a documentação ptt é tipo a mandar um tiro para o ar), mas em:

InetSocketAddress iaddr = new InetSocketAddress(InetAddress.getLocalHost(), 8000);

não tens de colocar o IP do servidor para ele aceitar conexões na rede e não apenas no localhost?

De facto isto funcionou, faz algum sentido :P

ou mesmo o "0.0.0.0"

E o 0.0.0.0 também, vai ficar este por defeito ;)
Obrigado a ambos, já aceita novas ligações.

Mas agora quando tento enviar um pacote por TCP do cliente para o servidor nada acontece, apenas no LogCat aparece isto muitas vezes:
07-17 17:41:14.759: D/dalvikvm(2890): GC_CONCURRENT freed 429K, 24% free 5256K/6855K, paused 1ms+1ms
Do servidor para o cliente já consegui enviar por TCP

Editado por renna, 17 July 2012 - 17:01.


#11 r3pek

r3pek

    Guru de Android

  • Former Staff
  • PipPipPipPipPip
  • 1560 mensagens
  • LocalizaçãoBA4 - Terceira - Açores
  • Nexus One + Motorola XOOM

Mensagem publicada 17 July 2012 - 19:09

E se tentares assim:

sChan.register(selector, SelectionKey.OP_ACCEPT | SelectionKey.OP_READ | SelectionKey.OP_CONNECT);