[ANDROID] ricevere messaggio su socket

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Scrivi risposta
Enry2108
Prode Principiante
Messaggi: 211
Iscrizione: venerdì 28 novembre 2008, 0:30
Località: Portomaggiore

[ANDROID] ricevere messaggio su socket

Messaggio da Enry2108 »

Ciao, sto scrivendo un applicazione che funziona da client, per un sistema client-server scritto in C.

Devo rimanere in ascolto sulla socket, e ricevere un byte, dove all'interno vi è una struttura messaggio.

Codice: Seleziona tutto

                     socket = new Socket(ip.getText().toString(), Integer.parseInt(porta.getText().toString()));
                    MainActivity.handler.obtainMessage(0, 0, -1, "Connessione avvenita con Successo!").sendToTarget();

                    DataInputStream in = new DataInputStream(socket.getInputStream());                 
                    byte[] buf11 = new byte[3000];               

                    while(flag){
                        in.read(buf11);
                        String a = new String(buf11,0,1);

                        if(!a.equals("\0")) {

                            Msg_rcv msg_rcv = new Msg_rcv();
                            Log.d(TAG, "msg_rcv creato");
                            msg_rcv.tipo_rcv = new String(buf11,0,1);
                            msg_rcv.mittente_rcv = new String(buf11,2,256);
                            msg_rcv.destinatario_rcv = new String(buf11,257,516);
                            msg_rcv.lunghezza_rcv = (new String(buf11,516,517));
                            msg_rcv.mess_rcv= new String(buf11,517,2500);

                            MainActivity.handler.obtainMessage(0, 0, -1, "Server: " + "tipo: " + msg_rcv.tipo_rcv + " mittente : " + msg_rcv.mittente_rcv + " destinatario: " + msg_rcv.destinatario_rcv + " lunghezza: " + msg_rcv.lunghezza_rcv + " messaggio: " + msg_rcv.mess_rcv).sendToTarget();
                            
                        }
                    }
il mio problema è che l'array nel quale vado a memorizzare il messaggio, mi rimane pieno e non so come svuotarlo una volta stampato a video il messaggio. qualcuno sa indirizzarmi? grazie
Avatar utente
SuperStep
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 2037
Iscrizione: lunedì 19 dicembre 2011, 16:26
Desktop: Unity
Distribuzione: Ubuntu 16.04 LTS x86_64
Sesso: Maschile
Località: Somma Vesuviana (NA)

Re: [ANDROID] ricevere messaggio su socket

Messaggio da SuperStep »

se utilizzi un ByteBuffer al posto di un byte, quello che puoi fare e' utilizzare il metodo flip e clear per pulirlo

http://docs.oracle.com/javase/7/docs/ap ... uffer.html
ubuntu 16.04 LTS 64-bit - Memoria: 31,3 Gib - Processore: Intel Core i7-5960X CPU @ 3.00 GHz × 16 - Grafica: AMD Radeon HD 7800 Series - Disco: SSD 256 GB x 4 (RAID 01)
Enry2108
Prode Principiante
Messaggi: 211
Iscrizione: venerdì 28 novembre 2008, 0:30
Località: Portomaggiore

Re: [ANDROID] ricevere messaggio su socket

Messaggio da Enry2108 »

Sto provando ad utilizzare ByteBuf, ho riscritto il pezzo di codice nel seguente modo:

Codice: Seleziona tutto

                  DataInputStream in = new DataInputStream(socket.getInputStream());
                         
                   byte[] buf11 = new byte[3000];

                    while(flag){       

                        in.read(buf11);

                        ByteBuffer bb = ByteBuffer.wrap(buf11);

                        Msg_rcv msg_rcv = new Msg_rcv();

                        bb.get(msg_rcv.tipo_rcv.getBytes(), 0, 1);

                        String a = msg_rcv.tipo_rcv.toString();

                        MainActivity.handler.obtainMessage(0, 0, -1, "Server: " + "tipo: " + a).sendToTarget();

                        bb.flip();
                        bb.clear();

                    }
Mi da un errore alla riga:

Codice: Seleziona tutto

bb.get(msg_rcv.tipo_rcv.getBytes(), 0, 1);
e non mi fa proseguire. A me sembra scritto in modo corretto, sto sbagliando ad utilizzare la funzione get?
Enry2108
Prode Principiante
Messaggi: 211
Iscrizione: venerdì 28 novembre 2008, 0:30
Località: Portomaggiore

Re: [ANDROID] ricevere messaggio su socket

Messaggio da Enry2108 »

Ok ho capito dove sbagliavo, ora funziona, risco a stampare solo il tipo, ma credo sia un problema di posizione dei byte.

l'unico problema è che mi stampa il messaggio due volte e non capisco il perchè, il ByteBuffer dovrebbe essere vuoto alla fine del while giusto?

Codice: Seleziona tutto

                     DataInputStream in = new DataInputStream(socket.getInputStream());

                    byte[] buf11 = new byte[3000];

                    while(flag){

                        in.read(buf11);

                        ByteBuffer bb = ByteBuffer.wrap(buf11);

                        Msg_rcv msg_rcv = new Msg_rcv();

                        msg_rcv.tipo_rcv = bb.get(0);
                        msg_rcv.mittente_rcv = bb.get(1);
                        msg_rcv.destinatario_rcv = bb.get(257);
                        msg_rcv.lunghezza_rcv = bb.get(516);
                        msg_rcv.mess_rcv = bb.get(517);

                        String tipo = new String(String.valueOf(msg_rcv.tipo_rcv));
                        String mittente = new String(String.valueOf(msg_rcv.mittente_rcv));
                        String destinatario = new String(String.valueOf(msg_rcv.destinatario_rcv));
                        String lunghezza = new String(String.valueOf(msg_rcv.lunghezza_rcv));
                        String mess = new String(String.valueOf(msg_rcv.mess_rcv));

                        MainActivity.handler.obtainMessage(0, 0, -1, "Server: " + "tipo: " + tipo + " mittente : " + mittente + " destinatario: " + destinatario + " lunghezza: " + lunghezza + " messaggio: " + mess).sendToTarget();

                        bb.flip();                   
                        bb.clear();
                        

                    }
Enry2108
Prode Principiante
Messaggi: 211
Iscrizione: venerdì 28 novembre 2008, 0:30
Località: Portomaggiore

Re: [ANDROID] ricevere messaggio su socket

Messaggio da Enry2108 »

Domanda:

io creo una classe

Codice: Seleziona tutto

public class Msg_rcv{
        private byte tipo_rcv;
        private byte mittente_rcv;
        private byte destinatario_rcv;
        private byte lunghezza_rcv;
        private byte mess_rcv;
    }
e riempio con:

Codice: Seleziona tutto

ByteBuffer bb1 = ByteBuffer.wrap(buf11,0,1);
                        msg_rcv.tipo_rcv = bb1.get();

                        ByteBuffer bb2 = ByteBuffer.wrap(buf11,1,256);
                        msg_rcv.mittente_rcv = bb2.get();

                        ByteBuffer bb3 = ByteBuffer.wrap(buf11,257,260);
                        msg_rcv.destinatario_rcv = bb3.get();

                        ByteBuffer bb4 = ByteBuffer.wrap(buf11,516,1);
                        msg_rcv.lunghezza_rcv = bb4.get();

                        ByteBuffer bb5 = ByteBuffer.wrap(buf11,517,1000);
                        msg_rcv.mess_rcv = bb5.get();
in questo modo, però io salvo un singolo byte, come faccio a mettere il contenuto di bytebuffer all'interno di un array?
Avatar utente
SuperStep
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 2037
Iscrizione: lunedì 19 dicembre 2011, 16:26
Desktop: Unity
Distribuzione: Ubuntu 16.04 LTS x86_64
Sesso: Maschile
Località: Somma Vesuviana (NA)

Re: [ANDROID] ricevere messaggio su socket

Messaggio da SuperStep »

allora, per l'ultima domanda, ovviamente basta creare un Array di ByteBuffer (oppure utilizzare una Struttura Dati gia' pronta: Queue, Stack, ...).

Per le altre: Dovresti creare il ByteBuffer fuori dal While, altrimenti non ha senso pulirlo, perche' quel Buffer viene riallocato ogni volta... Quindi dubito che non si pulisca se e' proprio un'altro buffer.
ubuntu 16.04 LTS 64-bit - Memoria: 31,3 Gib - Processore: Intel Core i7-5960X CPU @ 3.00 GHz × 16 - Grafica: AMD Radeon HD 7800 Series - Disco: SSD 256 GB x 4 (RAID 01)
Enry2108
Prode Principiante
Messaggi: 211
Iscrizione: venerdì 28 novembre 2008, 0:30
Località: Portomaggiore

Re: [ANDROID] ricevere messaggio su socket

Messaggio da Enry2108 »

Ho modificato la classe nel seguente modo:

Codice: Seleziona tutto

public class Msg_rcv{
        private byte[] tipo_rcv;
        private byte[] mittente_rcv;
        private byte[] destinatario_rcv;
        private byte[] lunghezza_rcv;
        private byte[] mess_rcv;
    }
e la funzione nel modo seguente:

Codice: Seleziona tutto

DataInputStream in = new DataInputStream(socket.getInputStream());
                    byte[] buf11 = new byte[3000];
                    ByteBuffer bb = ByteBuffer.wrap(buf11);


                    while(flag){
                        in.read(buf11);
                        Msg_rcv msg_rcv = new Msg_rcv();

                        bb.get(msg_rcv.tipo_rcv,0, 1);
                        bb.get(msg_rcv.mittente_rcv,1,256);
                        bb.get(msg_rcv.destinatario_rcv,258,256);
                        bb.get(msg_rcv.lunghezza_rcv,515,1);
                        bb.get(msg_rcv.mess_rcv,517,1000);

                        String tipo = new String(msg_rcv.tipo_rcv);
                        String mittente = new String(msg_rcv.mittente_rcv);
                        String destinatario = new String(msg_rcv.destinatario_rcv);
                        String lunghezza = new String(msg_rcv.lunghezza_rcv);
                        String mess = new String(msg_rcv.mess_rcv);

                         MainActivity.handler.obtainMessage(0, 0, -1, "Server: " + "tipo: " + tipo + " mittente : " + mittente + " destinatario: " + destinatario + " lunghezza: " + lunghezza + " messaggio: " + mess).sendToTarget();
                       
                    }
il codice ferma l'esecuzione a :

Codice: Seleziona tutto

bb.get(msg_rcv.tipo_rcv,0, 1);
, cosa sto sbagliando nella sintassi? mi pare di aver fatto tutto quello che mi hai suggerito.
Avatar utente
SuperStep
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 2037
Iscrizione: lunedì 19 dicembre 2011, 16:26
Desktop: Unity
Distribuzione: Ubuntu 16.04 LTS x86_64
Sesso: Maschile
Località: Somma Vesuviana (NA)

Re: [ANDROID] ricevere messaggio su socket

Messaggio da SuperStep »

probabilmente e' qualcosa di interno a bloccarsi, perche' non fai una cosa del tipo

Codice: Seleziona tutto

myByte = bb.get();
e poi splitti il tuo byte?

leggendo sulla documentazione: http://docs.oracle.com/javase/7/docs/ap ... nt,%20int)

i parametri sembrano messi correttamente. Quindi proverei prima a prendere tutto il buffer, e poi a splittarlo a mano.
ubuntu 16.04 LTS 64-bit - Memoria: 31,3 Gib - Processore: Intel Core i7-5960X CPU @ 3.00 GHz × 16 - Grafica: AMD Radeon HD 7800 Series - Disco: SSD 256 GB x 4 (RAID 01)
Enry2108
Prode Principiante
Messaggi: 211
Iscrizione: venerdì 28 novembre 2008, 0:30
Località: Portomaggiore

Re: [ANDROID] ricevere messaggio su socket

Messaggio da Enry2108 »

se ho capito bene, tu mi dici di estrarre tutto il contenuto del mio ByteBuffer, ed inserendolo in un nuovo array di byte (myByte) e poi estrarre da li il byte che mi servo. Giusto?

Anche secondo me da documentazione dovrebbe essere corretto. Infatti l'errore mi viene dato mentre l'applicazione è in esecuzione.
Avatar utente
SuperStep
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 2037
Iscrizione: lunedì 19 dicembre 2011, 16:26
Desktop: Unity
Distribuzione: Ubuntu 16.04 LTS x86_64
Sesso: Maschile
Località: Somma Vesuviana (NA)

Re: [ANDROID] ricevere messaggio su socket

Messaggio da SuperStep »

si, prova in quel modo. Fai un doppio passaggio.
ubuntu 16.04 LTS 64-bit - Memoria: 31,3 Gib - Processore: Intel Core i7-5960X CPU @ 3.00 GHz × 16 - Grafica: AMD Radeon HD 7800 Series - Disco: SSD 256 GB x 4 (RAID 01)
Enry2108
Prode Principiante
Messaggi: 211
Iscrizione: venerdì 28 novembre 2008, 0:30
Località: Portomaggiore

Re: [ANDROID] ricevere messaggio su socket

Messaggio da Enry2108 »

Ho risolto in questo modo:

Codice: Seleziona tutto

 DataInputStream in = new DataInputStream(socket.getInputStream());

               byte[] buf1 = new byte[1520];

                ByteBuffer bb = ByteBuffer.wrap(buf1);

                    while(flag){
                        in.read(buf1);
                        Msg_rcv msg_rcv = new Msg_rcv();
                   
                        byte[] b = new byte[bb.remaining()];
                        bb.get(b);

                        msg_rcv.tipo_rcv = new String(b ,0,1);
                        msg_rcv.mittente_rcv = new String(b ,1,256);
                        msg_rcv.destinatario_rcv = new String(b ,257,256);
                        msg_rcv.lunghezza_rcv = new String(b ,516,1);
                        msg_rcv.mess_rcv = new String(b ,517,1000);

                        MainActivity.handler.obtainMessage(0, 0, -1, "Server: " + "tipo: " + msg_rcv.tipo_rcv + " mittente : " + msg_rcv.mittente_rcv + " destinatario: " + msg_rcv.destinatario_rcv + " lunghezza: " + msg_rcv.lunghezza_rcv + " messaggio: " + msg_rcv.mess_rcv).sendToTarget();

                        bb.clear();
                    }
purtroppo continuo a ricevere 2 messaggi invece che uno soltanto.

E ovviamente ho i byte sballati.
Avatar utente
SuperStep
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 2037
Iscrizione: lunedì 19 dicembre 2011, 16:26
Desktop: Unity
Distribuzione: Ubuntu 16.04 LTS x86_64
Sesso: Maschile
Località: Somma Vesuviana (NA)

Re: [ANDROID] ricevere messaggio su socket

Messaggio da SuperStep »

posso consigliarti di provare la connessione a mano utilizzando telnet/netcat per capire cosa accade?

puo' essere che come hai utilizzato l'envelope per racchiudere i dati generi qualche sorta di errore. Magari la dimensione dei dati e' sballata di conseguenza non ti trovi.

Vorrei aggiungere una cosa che diminuisce le performance ma aumenta l'affidabilita' nella maggioranza dei dati.

Nei "piu' recenti" protocolli di intercomunicazione (esempio HTTP) tutti i dati sono rappresentati in formato stringa e passati in un header, il compito di ritrasformarli in un formato corretto se possibile ricade sull'altro nodo.

esempio:

Codice: Seleziona tutto

NODO1                      NODO2
data:
name: ValoreIntero -----> String "23" -----> Integer 23
value: Integer 23   
in questo caso potresti sfruttare librerie XML per metterci dentro i dati.

Oppure potresti creare un file JSON con dentro i dati spedire quel file, e recuperare i dati dall'altra parte.
ubuntu 16.04 LTS 64-bit - Memoria: 31,3 Gib - Processore: Intel Core i7-5960X CPU @ 3.00 GHz × 16 - Grafica: AMD Radeon HD 7800 Series - Disco: SSD 256 GB x 4 (RAID 01)
Enry2108
Prode Principiante
Messaggi: 211
Iscrizione: venerdì 28 novembre 2008, 0:30
Località: Portomaggiore

Re: [ANDROID] ricevere messaggio su socket

Messaggio da Enry2108 »

Il problema principale è che il Server dal quale io ricevo i dati, è un server C, il quale non può essere modificato. Quindi posso agire solo sul lato client dell applicazione android.

come dovrei fare con telnet per il controllo?
Avatar utente
SuperStep
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 2037
Iscrizione: lunedì 19 dicembre 2011, 16:26
Desktop: Unity
Distribuzione: Ubuntu 16.04 LTS x86_64
Sesso: Maschile
Località: Somma Vesuviana (NA)

Re: [ANDROID] ricevere messaggio su socket

Messaggio da SuperStep »

allora, ti basta aprire una comunicazione verso il server in questo modo:

telnet|netcat:

Codice: Seleziona tutto

telnet indirizzo porta
oppure
netcat indirizzo porta
dopodiche' spedire i dati a mano, oppure metterli in un file e passarli tramite questo:

Codice: Seleziona tutto

netcat 127.0.0.1 < miofileprovadati.dat
poi fai lo stesso emulando il server

Codice: Seleziona tutto

netcat -l portaserver
e provi a connettere la tua app android al server aperto con netcat. provi a mandare i dati a mano, e cerchi di capire dove sbaglia.
ubuntu 16.04 LTS 64-bit - Memoria: 31,3 Gib - Processore: Intel Core i7-5960X CPU @ 3.00 GHz × 16 - Grafica: AMD Radeon HD 7800 Series - Disco: SSD 256 GB x 4 (RAID 01)
Enry2108
Prode Principiante
Messaggi: 211
Iscrizione: venerdì 28 novembre 2008, 0:30
Località: Portomaggiore

Re: [ANDROID] ricevere messaggio su socket

Messaggio da Enry2108 »

prima di far le prove con telnet ho provato ad eseguire:

Codice: Seleziona tutto

                        bb.clear();
                        bb.hasRemaining();
                        Log.d(TAG, "PIENO: " + bb.hasRemaining());
e mi risulta true, quindi non sto svuotando correttamente il buffer. idee su come fare?
Avatar utente
SuperStep
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 2037
Iscrizione: lunedì 19 dicembre 2011, 16:26
Desktop: Unity
Distribuzione: Ubuntu 16.04 LTS x86_64
Sesso: Maschile
Località: Somma Vesuviana (NA)

Re: [ANDROID] ricevere messaggio su socket

Messaggio da SuperStep »

mi sono accorto solo adesso che hai rimosso

Codice: Seleziona tutto

bb.flip()
devi prima resettare la "posizione" di dove mettere i nuovi byte.

Nel primo post era corretto, devi fare:

Codice: Seleziona tutto

bb.flip();
bb.clear();
dopodichè avrai il tuo bytearray pulito.
ubuntu 16.04 LTS 64-bit - Memoria: 31,3 Gib - Processore: Intel Core i7-5960X CPU @ 3.00 GHz × 16 - Grafica: AMD Radeon HD 7800 Series - Disco: SSD 256 GB x 4 (RAID 01)
Enry2108
Prode Principiante
Messaggi: 211
Iscrizione: venerdì 28 novembre 2008, 0:30
Località: Portomaggiore

Re: [ANDROID] ricevere messaggio su socket

Messaggio da Enry2108 »

SuperStep [url=http://forum.ubuntu-it.org/viewtopic.php?p=4759141#p4759141][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:mi sono accorto solo adesso che hai rimosso

Codice: Seleziona tutto

bb.flip()
devi prima resettare la "posizione" di dove mettere i nuovi byte.

Nel primo post era corretto, devi fare:

Codice: Seleziona tutto

bb.flip();
bb.clear();
dopodichè avrai il tuo bytearray pulito.
Me nero accorto anche io, e l'ho inserito, ma il risultato non cambia, ricevo sempre un true dal controllo.

Ho anche provato a mettere i controlli prima del in.read

Codice: Seleziona tutto

 while(flag){
                       bb.flip();
                       bb.clear();
                        in.read(buf1);
ma non cambia nulla, il bytebuffer mi rimane pieno
Enry2108
Prode Principiante
Messaggi: 211
Iscrizione: venerdì 28 novembre 2008, 0:30
Località: Portomaggiore

Re: [ANDROID] ricevere messaggio su socket

Messaggio da Enry2108 »

nessun suggerimento?
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 4 ospiti