Go Down

Topic: Websocket [ci siamo quasi] (Read 13 times) previous topic - next topic

pablos

Ho trovato questo che potrebbe essere interessante
http://www.ermicro.com/blog/?p=1773

Quote
To comply with the HTTP protocol requirement, after sending the HTML response to the client we need to disconnect and close the connection with the client. These routines are implemented in the disconnect() and close() functionsThese two functions simply send the CR_DISCON (0×08) and CR_CLOSE (0×10) to the W5100 socket 0 command register (S0_CR) respectively as shown on this following C code:

...
// Send Disconnect Command
SPI_Write(S0_CR,CR_DISCON);
...

...
// Send Close Command
SPI_Write(S0_CR,CR_CLOSE);
no comment

lesto

#16
Jun 26, 2013, 11:57 am Last Edit: Jun 26, 2013, 12:01 pm by lesto Reason: 1
Quote
To comply with the HTTP protocol requirement

ed infatti quando invii la pagina HTML (quindi protocollo HTTP) la connessione poi la chiudi.

Ma per quanto riguarda la comunicazione TCP la connessione resta aperta ad oltranza, il TCP non pone limiti se non i time-out.

Quote
Ma la domanda è se apro e chiudo continuamente perdo il vantaggio di usare un socket? ritorno ad avere i tempi come con l'webserver tipo polling?

perdi un sacco di prestazioni, perchè bisogna rinegoziare la connessione TCP (three-way-handshake), però poi ritorni a comuniare SOLO le variabili che ti interessano.
Invece richiedendo la pagina HTTP hai la connessione TCP + invio GET + invio header risposta + invio HTML completo della risposta.

Insomma, coi websocket ci guadagni a priori.

Quote
durante lo scambio di dati se stacco il cavo ethernet arduino resta in timeout per circa 30 sec

Devi capire QUALE libreria inseriscfe questo time-out di 30 secondi e abbassarlo. Si tratta di modificare un numero, e probabilmente hai anche un metodo per farlo senza modificare la libreria in questione..

edit: devi sovrascrivere il timeout di default usato dalla EthernetShield:
http://forum.arduino.cc/index.php?topic=49401.0
Quote

You don't even need to modify the library code. In your sketch, add this include:

Code: [Select]
#include <utility/w5100.h>

then, in your setup, after you call Ethernet.begin(), add the following two lines:


Code: [Select]
W5100.setRetransmissionTime(0x07D0);
W5100.setRetransmissionCount(3);


That gives me a 3 second timeout on a bad server connection.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

PaoloP


pablos

#18
Jun 27, 2013, 01:15 am Last Edit: Jun 28, 2013, 01:16 am by pablos Reason: 1
sono rimasto sconcertato, mi spiego, cercavo di trovare i comandi vari per disconnettere il socket lato server e mi ero intestardito sul socket 0, aggiungendo allo sketch questo pezzo per ottenere un analisi dello stato dei 4 socket del w5100 mentre è indaffarato ho scoperto che lo ESTABLISHED è casuale ... sarà una stupidaggine ma non me lo aspettavo  :smiley-roll-blue:

Code: [Select]
void onData(WebSocket &socket, char* dataString, byte frameLength)
{  
 socket.send(dataString, strlen(dataString));
 String Dato_Ricev = (String)dataString;
 Serial.println(Dato_Ricev);
 
 if(Dato_Ricev == "status")//stringa inviata da browser mentre è aperto il sock e lo scambio dati
 {
    for (int i = 0; i < MAX_SOCK_NUM; i++)
    {
Serial << F("Socket#");
Serial.print(i);
uint8_t s = W5100.readSnSR(i);
Serial << F(":0x");
Serial.print(s,16);
Serial << F(" - Porta ");
Serial.print(W5100.readSnPORT(i));
Serial << F(" IP Client:");
uint8_t dip[4];
W5100.readSnDIPR(i, dip);
for (int j=0; j<4; j++) {
  Serial.print(dip[j],10);
  if (j<3) Serial << F(".");
}
Serial << F(" Porta (");
Serial.print(W5100.readSnDPORT(i));
Serial << F(")\n");
}
 
 }  
 Dato_Ricev ="";
}


provando 4 volte di seguito mi restituisce questo debug
Quote

Socket Connect
status
Socket#0:0x14 - Porta 80 IP Client:0.0.0.0 Porta (0)
Socket#1:0x17 - Porta 9990 IP Client:192.168.2.112 Porta (53172)
Socket#2:0x14 - Porta 9990 IP Client:0.0.0.0 Porta (0)
Socket#3:0x0 - Porta 0 IP Client:0.0.0.0 Porta (0)
Socket Disconnect

Socket Connect
status
Socket#0:0x0 - Porta 80 IP Client:192.168.2.112 Porta (53488)
Socket#1:0x17 - Porta 9990 IP Client:192.168.2.112 Porta (53492)
Socket#2:0x14 - Porta 9990 IP Client:0.0.0.0 Porta (0)
Socket#3:0x14 - Porta 80 IP Client:192.168.2.112 Porta (53486)
Socket Disconnect

Socket Connect
status
Socket#0:0x17 - Porta 9990 IP Client:192.168.2.112 Porta (53497)
Socket#1:0x14 - Porta 80 IP Client:192.168.2.112 Porta (53492)
Socket#2:0x14 - Porta 9990 IP Client:0.0.0.0 Porta (0)
Socket#3:0x0 - Porta 80 IP Client:192.168.2.112 Porta (53493)
Socket Disconnect

Socket Connect
status
Socket#0:0x17 - Porta 9990 IP Client:192.168.2.112 Porta (53506)
Socket#1:0x0 - Porta 80 IP Client:192.168.2.112 Porta (53503)
Socket#2:0x14 - Porta 9990 IP Client:0.0.0.0 Porta (0)
Socket#3:0x14 - Porta 80 IP Client:192.168.2.112 Porta (53493)
Socket Disconnect


La lista di quelle istruzioni sono dentro la lib utility/socket.h http://code.google.com/p/arduino/source/browse/trunk/libraries/Ethernet/utility/w5100.h?r=1088

osservando la libreria ... class SnSR e sostituendo i risultati, i 4 socket sono in questo stato (nella prima connessione)

Socket#0: ... static const uint8_t LISTEN      = 0x14;
Socket#1: ... static const uint8_t ESTABLISHED = 0x17;
Socket#2: ... static const uint8_t LISTEN      = 0x14;
Socket#3: ... static const uint8_t CLOSED      = 0x00;


i passaggi sono:
1) Mi sono connesso con la porta 80 per farmi mandare la pag html ed ha preso il primo socket libero (lo 0)
2) ho avviato la connessione socket e ha preso il socket 1, ma lo 0 non dovrebbe essere libero dal momento che c'è un close sulla 80 al termine della pagina trasferita?

l'ip del client è giusto 192.168.2.112 è quello del pc con il quale mi sono collegato però quelle porte da dove sono uscite? le sceglie il mio SO windows?
alcuni socket hanno una porta assegnata senza ip ... vengono scelti a casaccio mi pare :)

vabbè domani farò le prove su tutti i sock, se non altro ho capito che cercando il codice 0x17 so quali e quanti socket sono in "connessione stabilita" ma non ho capito perchè 2 sock sono sempre in stato LISTEN

ciao
no comment

lesto

che ti dia differenti socket non è un problema... fintanto che raggiunta la 4° connessione ti assegni ancora socket :)

le porte in uscita sono scelte a random dal SO, ma possono anche essere espressamente richieste (mai vista una richiesta esplicita, ma è possibile), ed è il motivo per cui di base i firewall sono impostabili per le porte in entrata (inbound) ma non in uscita (outbound)

Quote
alcuni socket hanno una porta assegnata senza ip

che siano "in ascolto" di una connessione?
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

pablos

#20
Jun 27, 2013, 12:39 pm Last Edit: Jun 27, 2013, 12:52 pm by pablos Reason: 1
Ora ho un altro problema non mi uccidere :)

Come apro il socket da ip pubblico?

ho sul router un reindirizzamento di tutto ciò che arriva da web sulla porta 9300 la quale reindirizza tutto su arduino 192.168.2.177 e fin qui va bene, fino a oggi scrivendo 2.xxx.xxx.xxx:9300 facevo quello che volevo
Ho aggiunto al router un altra porta ... la 9990 reindirizzata su 192.168.2.177 (con restart) ma nulla

in rete locale metto ws://192.168.2.177:9990/ws e funziona bene

ora su ip pubblico 2.xxx.xxx.xxx:9300 carico la pagina sul browser (e va bene)  .... poi cosa metto nell'indirizzo?

ws://2.xxx.xxx.xxx:9990/ws                 socket error
ws://http://2.xxx.xxx.xxx:9990/ws        socket error
http://2.xxx.xxx.xxx:9900                     mi ricarica la pagina (ovvio ho aggiunto un altro ingresso sul router)

sai cosa devo scrivere in quella barra? sembra che da fuori arrivi tutto sulla 80 e quindi ignorato dalla funzione socket dello sketch

grazie per l'aiuto
ciao

no comment

lesto

Quote
in rete locale metto ws://192.168.2.177:9990/ws e funziona bene

quindi in teoria
Quote
ws://2.xxx.xxx.xxx:9990/ws 


sicuro di redirigiere la 9990 in entrata sulla 9990 del .177 ? perchè volendo potresti aver settato diverse porte..
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

pablos

#22
Jun 27, 2013, 02:22 pm Last Edit: Jun 27, 2013, 07:17 pm by pablos Reason: 1
si, ma non hai guardato l'immagine  :smiley-roll: .... questo indirizzo non viene scritto sulla barra del browser ma nel file.js nel valore (val) del campo wsServer

ws = new WebSocket($('#wsServer').val());
                                                   |
                                                   |____________________ ws://192.168.2.177:9990/ws
no comment

lesto

no, scusa, le immagini sono bloccate a lavoro e non vedo nemmeno il simbolo di immagine mancante (questo però è un "bug" del forum)

edit: ma tu come lo hai ricavato il tuo ip pubblico?
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

pablos

#24
Jun 27, 2013, 06:44 pm Last Edit: Jun 27, 2013, 07:22 pm by pablos Reason: 1

edit: ma tu come lo hai ricavato il tuo ip pubblico?

Come fanno tutti con my Ip ... ed è raggiungibile da tutti i gestori wind, alice, infostrada, reti wifi pubbliche ingiro per la città, ecc,  ormai sono 3 anni che ho sempre quello, che gli utenti FW in qualche modo siano sempre dentro una nat non lo so con esattezza posso informarmi facilmente sul metodo che usano eventualmente.   

Comunque ce l'ho fatta ho dovuto impostare tutti e 2 i router e fastweb è parecchio noioso sulle porte non lascia passare nulla
Mi piace!! posso fare un logger e salvare data/ora e gli ip remoti che si collegano ad arduino :)

se dovesse servire a qualche fastwebbino allego i setup dei 2 router

riguardo a quello che avevi detto qualche post fa "fare un array di wsServer"

In teoria parlare sulla stessa porta http non dovrebbe creare grossi problemi se non la complessità aggiunta.

Secondo me se troviamo il modo di fare una specie di "sockt.stop" come si fa con client.stop, non servono porte diverse, sarebbe utile avere 4 porte diverse se avessi in rete 4 arduini che comunicano informazioni diverse tra loro, ma nel mio caso tutti i client ricevono le stesse informazioni
Se la porta 80 riesce a gestire tanti client facendo open-close infiniti li serve tutti, perchè no sulla 9990?

che dici è una scemenza visto che parliamo di un tipo di connessione diversa?


ciao
no comment

lesto

#25
Jun 27, 2013, 09:14 pm Last Edit: Jun 27, 2013, 10:09 pm by lesto Reason: 1
no, dico che hai ragione, in pratica anche sull'80 i vari socket connessi sono riconosciuto perchè ad ogni pacchetto inviano ip e PORTA DI ORIGINE (quella random da parte del SO) e porta di arrivo. è una combinazione unica, ed in realtà poi essere ancora più sicuro segendo gli ack number trasmessi dalle due parti (vedi trama del pacchetto TCP).
Certo è una gestione che diventa un pò complessa, ma facle da nascondere. e strano che non puoi disconnettere lato server.. forse basta chiamare il distruttore?

edit: anzi! mi apsetto che il WebSocket al suo interno abbai un socket della wiznet... quindi magari esiste un modo per farselo dare

edit2: link alla libreria websocket?
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

pablos

#26
Jun 28, 2013, 12:12 am Last Edit: Jun 28, 2013, 12:30 am by pablos Reason: 1
hai ragione ... la lib più aggiornata l'ho presa qui https://github.com/ejeklint/ArduinoWebsocketServer

la libreria contiene questa classe che però quando la chiami da sketch da errore ... dice che è privata
Code: [Select]
void WebSocket::disconnectStream() {
   client.flush();
   delay(1);
   client.stop();
}


no comment

lesto

se è privata vuol dire che viene usata internamente dalla libreria, e che tu non dovresti toccarla
ifatti dal readme:

Quote
The server only handles one client at a time. Trying to connect two at the same time will force the old client to disconnect.
There's no keep-alive logic implemented.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

pablos

#28
Jun 28, 2013, 12:32 am Last Edit: Jun 28, 2013, 12:42 am by pablos Reason: 1
si viene richiamata da

Code: [Select]
void WebSocket::listen()
se if (getFrame() == false)


se volessi renderla pubblica e richiamarla?
ho provato a inserirla come pubblic: ecc ecc  ... compila però quando la uso mi da sempre errore, è evidente che non ho classe nelle classi :)
no comment

lesto

non puoi semplicemente renderlapubblica, o meglio puoi, però poi tutto ilresto della classe che confida nel fatto che sia chiamata in certi momenti specifici (infatti è private apposta per evitare che tu possa fare casini)

in questo casola soluzione è:
crea un metodo disconnetti:
Quote

void disconnect(){
   #ifdef DEBUG
      Serial.println("Disconnecting");
   #endif
  if (state != DISCONNECTED ) {
      disconnectStream();
      state = DISCONNECTED;
      if (onDisconnect) {
          onDisconnect(*this);
      }
  }
}


ovvimente va aggiunto anche le .h come public.

e in listen, giusto per essere completi, cambia
Code: [Select]
if (getFrame() == false) {
                   // Got unhandled frame, disconnect
#ifdef DEBUG
Serial.println("Disconnecting");
#endif
                   disconnectStream();
                   state = DISCONNECTED;
                   if (onDisconnect) {
                       onDisconnect(*this);
                   }
               }


in

Code: [Select]
if (getFrame() == false) {
                   // Got unhandled frame, disconnect
disconnect();
               }


ora, si può modificare il codice per reggere più client, basta che trasformi "client" in un array e aggiusti il codice di conseguenza.
Però è bruttissimo avere 2 server.

Volendo in doHandshake() come puoi notare legge l'header inviato per capire se il websocket è supportato. Se quella richiesta fallisce

Code: [Select]
if (hasUpgrade && hasConnection && isSupportedVersion && hasHost && hasOrigin && hasKey) {
puoi servire la tua pagina HTML!

ed ecco che magicamente una sola porta dovrebbe bastare a servire la pagina + connessioni WebSocket.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Go Up