Pages: 1 [2] 3 4 ... 13   Go Down
Author Topic: Websocket [ci siamo quasi]  (Read 8159 times)
0 Members and 1 Guest are viewing this topic.
Genova
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2757
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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);
Logged

Meglio imparare dalle cose inutili piuttosto che non imparare niente.   [Arduino Mega R3 + Ethernet shield W5100 + SD card 8Gb FAT32]

0
Online Online
Shannon Member
****
Karma: 117
Posts: 10112
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#include <utility/w5100.h>

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


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

That gives me a 3 second timeout on a bad server connection.
« Last Edit: June 26, 2013, 05:01:21 am by lesto » Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 104
Posts: 6616
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

x iscrizione
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Genova
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2757
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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 smiley

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
« Last Edit: June 27, 2013, 06:16:01 pm by pablos » Logged

Meglio imparare dalle cose inutili piuttosto che non imparare niente.   [Arduino Mega R3 + Ethernet shield W5100 + SD card 8Gb FAT32]

0
Online Online
Shannon Member
****
Karma: 117
Posts: 10112
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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?
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Genova
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2757
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ora ho un altro problema non mi uccidere smiley

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



* client sock.jpg (18.16 KB, 944x604 - viewed 24 times.)
« Last Edit: June 27, 2013, 05:52:18 am by pablos » Logged

Meglio imparare dalle cose inutili piuttosto che non imparare niente.   [Arduino Mega R3 + Ethernet shield W5100 + SD card 8Gb FAT32]

0
Online Online
Shannon Member
****
Karma: 117
Posts: 10112
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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..
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Genova
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2757
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
« Last Edit: June 27, 2013, 12:17:55 pm by pablos » Logged

Meglio imparare dalle cose inutili piuttosto che non imparare niente.   [Arduino Mega R3 + Ethernet shield W5100 + SD card 8Gb FAT32]

0
Online Online
Shannon Member
****
Karma: 117
Posts: 10112
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Genova
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2757
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley

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


* router.jpg (183.71 KB, 927x932 - viewed 23 times.)
« Last Edit: June 27, 2013, 12:22:29 pm by pablos » Logged

Meglio imparare dalle cose inutili piuttosto che non imparare niente.   [Arduino Mega R3 + Ethernet shield W5100 + SD card 8Gb FAT32]

0
Online Online
Shannon Member
****
Karma: 117
Posts: 10112
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
« Last Edit: June 27, 2013, 03:09:45 pm by lesto » Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Genova
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2757
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
void WebSocket::disconnectStream() {
    client.flush();
    delay(1);
    client.stop();
}

« Last Edit: June 27, 2013, 05:30:26 pm by pablos » Logged

Meglio imparare dalle cose inutili piuttosto che non imparare niente.   [Arduino Mega R3 + Ethernet shield W5100 + SD card 8Gb FAT32]

0
Online Online
Shannon Member
****
Karma: 117
Posts: 10112
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Genova
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2757
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

si viene richiamata da

Code:
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 smiley
« Last Edit: June 27, 2013, 05:42:21 pm by pablos » Logged

Meglio imparare dalle cose inutili piuttosto che non imparare niente.   [Arduino Mega R3 + Ethernet shield W5100 + SD card 8Gb FAT32]

0
Online Online
Shannon Member
****
Karma: 117
Posts: 10112
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
if (getFrame() == false) {
                    // Got unhandled frame, disconnect
#ifdef DEBUG
Serial.println("Disconnecting");
#endif
                    disconnectStream();
                    state = DISCONNECTED;
                    if (onDisconnect) {
                        onDisconnect(*this);
                    }
                }

in

Code:
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:
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.
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Pages: 1 [2] 3 4 ... 13   Go Up
Jump to: