Websocket [ci siamo quasi]

Buongiorno a tutti

Ho fatto alcuni esperimenti per ottenere su browser client le informazioni di stato dei 70 pin del 2560 in real time, devo ammettere che rispetto al polling il micro (nonostante sia piccolo e debole) nemmeno se ne accorge, sono rimasto stupefatto (più stupe che fatto) il loop non subisce alcun rallentamento per quanto sia vasta la mole di informazioni scambiate.
Tutto questo fino a quando la pagina html si trova sul PC, il mio intento è quello di mettere la pagina su SD come si fa con il classico webserver su sd, ma solo che la comunicazione dati che deve poi stabilirsi è di tipo socket

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept:

Non esiste su internet nessun progetto di questo tipo per arduino che comprenda un insieme di opzioni, ho cercato davvero tanto e c'è molto, tutto rivolto però a pagine su server esterni, processing, python o app già pronte e installate su smartphone

Quindi quello che vorrei ottenere è:

  • Le pagine html devono risiedere su SD di arduino e poter essere scaricate su browser alla semplice connessione http//192.168.x.x:nnnn/xxxx
  • Una volta ottenuta la pagina lo scambio di dati deve avvenire su protocollo http tramite socket alla pressione di un button "connect" o ancora meglio automatica al document.ready
  • L' webserver su arduino deve riconoscere se la richiesta GET o POST è di tipo "mandami un file" o "mandami i dati"
  • Deve poter ricevere da remoto l'upload di file
  • Deve essere supportato dai browser dei diversi smartphone (tutti)

Ho modificato la tinywebserver che svolge gran parte del lavoro, riconosce che la connessione è tipo socket ma non è in grado di gestirla per questo c'è la WebSocket.h che lo fa bene ...

1° problema: le 2 librerie non possono coesistere dal momento che entrambe sono in ascolto su "if client connected", fanno a cazzotti tra loro ed entrambe rispondono a richieste GET ciascuna interpretandole in modo diverso

2° problema: su android per ora ho il messaggio "this browser not support socket service" sugli altri SO non lo so.

So che esistono librerie su JS tipo socket.io.js o node.js Socket.IO che aiutano, chiedo se qualcuno si è mai cimentato in questa impresa e ha voglia di collaborare o suggerire la strada migliore.

Grazie

Ciao

Per il punto uno puoi provare ad usare due porte diverse per il server.

Grazie big, il socket lavora già su una porta diversa dalla 80, ma mi hai fatto venire un idea

ciao

Un primo passo, funziona caricando il file htm da SD oppure anche aprendo il file sul PC in locale/remoto va bene lo stesso
L'esempio invia un numero int progressivo al client visualizzandoli col metodo append

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#include <WebSocket.h> 
#include <Flash.h>

#define MAX_FRAME_LENGTH 64
#define PREFIX "/ws"
#define PORT0 9990
#define PORT1 9991
#define PORT2 9992
#define PORT3 9993
// Create a Websocket server listening to http://192.168.2.177:9990/ws/ 
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,2, 177 };

File htmlFile;
EthernetServer server(80);

unsigned long previousMillis_e = 0;
const byte interval_e = 10; //led lampeggiante

int lamp_led;
int var_test_send =0;

WebSocket wsServer0(PREFIX, PORT0);
WebSocket wsServer1(PREFIX, PORT1);
WebSocket wsServer2(PREFIX, PORT2);
WebSocket wsServer3(PREFIX, PORT3);

void onConnect(WebSocket &socket) 
{
  Serial << F("Socket Connect\n");
}

void onData(WebSocket &socket, char* dataString, byte frameLength)
{  
  socket.send(dataString, strlen(dataString));
  String Dato_Ricev = (String)dataString;
  Serial.println(Dato_Ricev); //ritorno del msg scritto su client
  Dato_Ricev =""; 
}

void onDisconnect(WebSocket &socket) 
{
  Serial << F("Socket Disconnect\n");
   wsServer0.begin();
}
 
void setup()
{
  pinMode(10, OUTPUT); digitalWrite(10, 1); 
  pinMode(4, OUTPUT);  digitalWrite(4, 1); 
  pinMode(3, OUTPUT); // led lampeggiante sistema in funzione (mi indica visivamente un rallemtamento o se e' inchiodato)
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  server.begin();
  if (!SD.begin(4)) { return; }
  
  wsServer0.registerConnectCallback(&onConnect);
  wsServer0.registerDataCallback(&onData);
  wsServer0.registerDisconnectCallback(&onDisconnect);  
  wsServer0.begin();
  
  //W5100.init();
  //W5100.writeSnMR(s, SnMR::MACRAW); 
  //W5100.execCmdSn(s, Sock_OPEN); 
}
 
void loop()
{
  if(millis() - previousMillis_e > interval_e) 
  {   
       previousMillis_e = millis();             
                     
        //-------------------------------led lampeggiante P3 verde se OK -------------------------
        lamp_led++;
        if(lamp_led == 10)  digitalWrite(3,1);               
        if(lamp_led == 20){ digitalWrite(3,0); lamp_led=0; } 
        //----------------------------------------------------------------------------------------
  } 
  
  wsServer0.listen();
    
  if (wsServer0.isConnected()) // entra qui con connessione su porta 9990
  { 
       var_test_send++;
       String test= (String)var_test_send;      
       char StrChar[50];
       test.toCharArray(StrChar, 50);
       wsServer0.send(StrChar, 10);    
  }  
  
  EthernetClient client = server.available(); //entra qui con connessione su porta 80
  if (client ) 
  {
    boolean currentLineIsBlank = true;
    while (client.connected()) 
    {
      if (client.available()) 
      {
        char c = client.read();
        if (c == '\n' && currentLineIsBlank) 
        {
          client << F("HTTP/1.1 200 OK\r\n");
          client << F("Content-Type: text/html\r\n");
          client << F("\r\n");
                  
          htmlFile = SD.open("client.htm");
          if (htmlFile) {
              while (htmlFile.available()) {
                client.write(htmlFile.read());
            }
            htmlFile.close();
          }
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
  }
}

Resta da vedere

  • più connessioni simultanee con assegnazione automatica della porta, al momento una seconda connessione da altri client disconnette il primo
  • Non funziona sugli smarphone, dovrebbe essere sufficiente cambiare metodo e libreria sull'html

ciao

26/06/13

  • correzione sketch stringhe flash errate
  • aggiunto l'echo sul serial dei messaggi trasmessi dal client

x iscrizione, ho sempre pensato di lavorare cin i websocket.
In teoria parlare sulla stessa porta http non dovrebbe creare grossi problemi se non la complessità aggiunta.

la libreria usi JQuery? cerca "godville", usano i "turbosocket", che è una libreria fatta olto bene e dedicaata solo a quello (jquery ti porti dietro un sacco di roba per nulla, credo)

Non ho trovato molto su "godville" a parte che è un videogame :), con altre chiavi è uscito "goodwill socket" un socket mobile e altre cosette sul market android dei tarocchi aptoide, magari se lo cerchi tu che sai di cosa parli lo trovi subito ... comunque

Sarebbe possibile usare 4 socket senza disturbare gli altri, l'ho fatto e funziona .... basta mettere questo:

if (wsServer1.isConnected()) // entra qui con connessione su porta 9991
  { 
       ...
       ...
       wsServer1.send(StrChar, 10);   

if (wsServer2.isConnected()) // entra qui con connessione su porta 9992
  { 
       ...
       ...
       wsServer2.send(StrChar, 10);    

if (wsServer3.isConnected()) // entra qui con connessione su porta 9993
  { 
       ...
       ...
       wsServer3.send(StrChar, 10);     
  }

se digiti da browser http://192.168.2.177 va sulla porta 80 caricandoti la pagina senza chiudere i socket degli altri client
però non è che mi piaccia molto ... bho ora vediamo che si può fare

ciao

esatto è un web-browser testuale, solo che per aggiornarsi invece che ricaricare la pagina usa i websocket.. e funziona veramente bene, mi pare anche con molto cellulari, perchè usano "Comet", ovvero un framework di fall-back nel caso nonfunzionino i websocket nativamente

more info:
http://wiki.godvillegame.com/Turbo_mode#Technical_details

edit:

però non è che mi piaccia molto

un array di wsServer, no? :smiley:

Lesto sei tu l'informatico non io ... dai su butta giù qualcosa :smiley:

penso che ci stia bene questa

Un uomo su un pallone aerostatico finisce su un albero in mezzo alle campagne in una zona desolata. Passa di li una persona, allora l'uomo sul pallone gli chiede: "Scusi, mi sa dire dove ci troviamo?" "Guardi, lei si trova su un albero, a dieci metri di altezza, siamo a 40 km dal centro abitato piu vicino e io non ho una scala per farla scendere" "Senta, lei nella vita si occupa di sistemi informatici?" "Perbacco, come fa a saperlo?" "Vede, lei mi ha fatto una perfetta analisi della situazione, ma non mi ha dato la minima soluzione per risolvere i miei problemi". "Senta" gli risponde l'altro "lei nella vita è un dirigente in qualche azienda?" "Caspita, come lo sa?" "Perche, vede, lei sta nella merda, non sa cosa fare, ma ha trovato il modo di dare la colpa ad un altro!!!!!!!"

mi passi un'analisi del trafico con wireshark?

Ma mi hai preso per un vigile urbano? :smiley: :smiley: :smiley: :smiley:

davvero se non lo sai, sallo! ti aiuta un sacco, anche a debuggare problemi inaspettati di altri SW, sopratutto quando vuoi "sostituirti" ad uno dei due attori :grin:

ah, dimenticavo:

se digiti da browser http://192.168.2.177

questo è il tuo ip locale. Se hai FB(fastweb, perchè in realtà iuna internet parallela dei soli suoi utenti che poi si colleva alla "internet" he conosciamo tramite GATEWAY, e questi fanno da "filtro") nessuna possibilità che io ti possa vedere se non PAGHI l'ip pubblico(in pratica i GATEWAY accettano il traffico verso la tua macchina), o che io non mi faccia FB. X altre compagnie clicca su www.mioip.it e vedi il tuo IP pubblico. Ora, essendo uno il tuo ip e mille i tuoi PC, come fa il router a sapere a quale pc redirigere le richieste sulla porta 80 e sulla 999X? semplice, glie lo dici tu! Vedi cqualche guida su come aprire le porte su Emule o simili. (NAT, se vuoi studiare la tecnologia. DIFFICILMENTE hai un ip pubblico per ogni PC; lo hai con FB ma solo nella rete FB, in tal caso si parla di FIREWALL, ma peccato che gli HUB siano intoccabili che io sappia)

Perchè mi fai questa lezione di ip pubblico e forwarding vari su router...non era inteso nella risposta.

Raggiungo arduino da 2 anni su ip pubblico statico senza problemi ho provato subito il programma qui sopra e funziona bene, comunque se non lo avessi basterebbe un dyndns per risolvere.

Però sei rimasto indietro .... su fibra ottica fastweb può facilmente dare l'ip statico a chi non lo ha e i nuovi lo ottengono di default.... cosa che resta ancora difficile su adsl ... ho l'ip statico free da 3 anni ... pago fastweb da 14 anni vorrei un po' vedere :slight_smile: :fearful:... farebbero qualunque cosa per tenersi il cliente.
prima gli ip dinamici erano 10.x.x.x ora sono 2.x.x.x
Chi ha fibra ormai sono quasi tutti su ip statico anche per una questione legale, di sicurezza e di controllo utenti.
Tutti nel prossimo futuro avranno ip statico, è solo questione di tempo, ma non sarà un vantaggio, il grande fratello potrà controllarci meglio!!!

Ti farò avere il traffico se pensi sia utile, in questi giorni non so quante ore di libertà ho :slight_smile: causa lavori da finire pre-ferie, farò il possibile

ciao

allora, paritamo dalle basi:
come avrai notato, il protocollo HTTP è limitato, nel senso che il chliet fa una GET, il server risponde e chiude la connessione. fine. Non esiste modo (se non tramite alcuni artifizi tipo cookie, ma stiamo andando fuori dal seminato) di identificare univocamente un utente, per natura del protocollo HTTP.

Ora, come ben sappiamo il protocollo HTTP però si basa sui socket, che fanno uso del protocollo TCP: il protocollo TCP è monto simile (per il programmatore finale, NON come protocollo in se) come una Seriale: tu hai un oggetto, che una volta inizializzato, scrivi e ricevi byte, fino a che non lo chiudi. Che poi dietro ci sia un cavo USB, Eth o altro poco importa (senza entrare nei particolari).

Qundi ci si è detto: ma è stupido perdere la potenza del protocollo TCP, che è bidirezionale e PERSISTENTE in cambio di un protocollo QUASI MONODIREZIONALE e ONE-SHOT.
Da che sono nati i WebSocket: tu puoi stabilire una comunicazione TCP persistente da una pagina HTML: quindi avrai un solo passaggio da HTTP, e il resto da TCP puro.

Quindi a questo punto hai una modo per parlare alla pagina.

Ora. volessimo passare dei dati basta fare, da entrambe le direzioni, una semplice write/read come faremmo da seriale: sarà poi compito del javascript che riceve capire dovee come inserire il dato ricevuto a sostituzione di quello nuovo modificando gli elementi HTML, o viceversa.

Quindi nasce il problema: cse vogliamo fare una libreria di utilità, essa dovrà essere sia lato arduino per cui tu farai (esempio, è proprio questa struttura che dobbiamo discutere):

WebSocket.print("valore1:");
WebSocket.println(a);

notare che in questo caso ci sono 2 valori speciali: il :, che divide il nome variabile dalla variabile, e il '\n', usato per indicare la fine della variabile. Ciò vuol dire che il nome variabile NON potrà contenere il valore ':', e il valore della variabile non potrà contenere '\n', (quindi se anche solo uno dei byte che compone a vale '\n', l'algoritmo sfasa)

poi ci sarà anche il lato libreria JS, che seguendo uno schema preciso alimenterà un array di array di byte con id stabilito(magari proprio quel 'valore 1' dell'esempio di prima, quindi quel 'valore 1' avrà alte limitazioni dettate dall'HTML, quindi userei un ID numerico preceduto da ID per eliminare ogni problema, es. "ID213"), che conterrano i valori che automagicamentesi aggioreranno, e che saranno "invisibili" (style="display:none;")

Infine quella generata è PARTE della pagina HTML, con solo i div e il javascript; vengono infine incollati in testa e in coda due file tipo inizio.html e fine.html che l'utente può personalizzare;di default conterrano un un semplice script che scorrendo tutti gli array li mostrerà come HEX o come stringa (da decidere) in un div, ne setta la posizione e presenta i dati in maniera "decente". Sta poi all'utente personalizzare come vuole il JS di esempio.

Ora, una (bella secondo me) soluzione è creare una libreria che:
setti varialidi di in/out e RICEVI il rispettivo numero (chepoi sarà l'index nell'array); metti a disposizione get e set di queste variabili. se una variabile è sia in che out basterà settarla sia come in che out.
Notare che tutte le variabili, per semplicità, saranno trattate lato JS e Arduino come Array di BYTE, e lato JS in automatico MOSTRATE come STRINGHE o in HEX, da decidere; In questo modo gli esempi base usarenno le stringe e converitanno i numeri in stringhe, che poi saranno a loro volta inviate alla libreria come array di char, magari nascondendo la cosa; un utentesmaliziato può invece slegarsi dalle stringhe e ottimizzare inviando i byte grezzi.

@pablos: come sei messo a classi in c++? vedo che sai usarle (anche se non lo sai), ma SCRIVERLE? e a puntatori? leo imparò proprio con la sua swRTC a scrivere le classi, e hai visto che fine ha fatto :smiley:

btw se invece interessa la via "facile"

WebSocket wsServer0(PREFIX, PORT0);
WebSocket wsServer1(PREFIX, PORT1);
WebSocket wsServer2(PREFIX, PORT2);
WebSocket wsServer3(PREFIX, PORT3);

può diventare pseudocodice eh.. oggi giornata pesante :sweat_smile:

WebSocket wsServer[SIZE];
const int PORT_BASE = 9990;
setup(){
  for i < SIZE{
     wsServer[i] = new wsServer(PREFIX, PORT_BASE+i);//equivale a *alloc() del C
  }
}

ATTENTO PERO': hai usato l'allocazione DIANMICA della memoria con la NEW! ciò vuol dire che se ora fai

wsServer[i] = new wsServer(PREFIX, PORT_BASE+i);

la vecchia wsServer RIMANE ad occupare RAM, ma ne hai perso qualsiasi riferimeto, e quindi è ram "bloccata e inutilizzabile": in termine tecnico "garbage", ma il C++ ne il C possiedono un garbage collector. Devi dunque essere TU a rilasciare le risorse:

if (wsServer[i] != null){
   delete wsServer[i]; //equivale a free(wsServer[i]); del C
   wsServer[i] = null; //assicuriamoci di non usare per sbaglio il riferimento alla variabile che è stata distrutta
}
wsServer[i] = new wsServer(PREFIX, PORT_BASE+i);

In generale, mooooolto meglio se fai le NEW SOLO nel setup, e poi gli oggetti li usi ma non li "distruggi", eviti TAAANTI sbattimenti.

pablos:
Perchè mi fai questa lezione di ip pubblico e forwarding vari su router...non era inteso nella risposta.

non conosco il tuo livello di preparazione, a priori metto le mani avanti così rimane anche traccia ad un eventuale interessato che queste cose non le sa :grin:
anchela risposta che ho appena scritto è abbastanza eusastiva "fuori tema", ma perchè non ho capito bene i tuoi obbiettivi. Io, come per leo, sono disposto a darti le basi e correggerti, anzi anche di più essendo una cosa che come già ti dissi mi interessa da un pò

pablos:
Raggiungo arduino da 2 anni su ip pubblico statico senza problemi ho provato subito il programma qui sopra e funziona bene, comunque se non lo avessi basterebbe un dyndns per risolvere.

stai confondendo ip statico con ip pubblico(inteso al di fuori della rete Fastweb).
Poi magari quando ti hanno dato l'ip statico ti hanno dato ANCHE l'ip pubblico (FB è dietro una gigante NAT in modo da poter usare pochi IPv4 sulla vera internet, che costano, ma ovviamente il problema scompare con IPv6)

Grazie lesto della spiegazione.
L'obbiettivo sarebbe quello di impegnare il meno possibile la ethernet con un traffico veloce e realtime, se uno ad esempio volesse comandare in casa tramite wifi un robottino deve usare un socket per forza.
E' un miglioramento rispetto al classico webserver, ma finchè non ne ricavo i vantaggi non so dire se è davvero un ottimizzazione.

Riguardo alla mia preparazione il c/c++ l'ho visto qui con arduino e le classi non le ho ben chiare diciamo che tiro a cavamerla guardando e cecando di capire il lavoro degli altri :D.
Una libreria sulla gestione ethernet socket da zero non penso proprio che riuscirei a farla, ma perchè dovremmo ce ne sono tante, basta migliorarne una secondo le necessità.

Prima di passare a fare tante cosette voglio capire quanto sia efficiente questo tipo di protocollo lavorando sul dettaglio di vari eventi che possono accadere, perchè ad esempio un grosso difetto che non mi sta bene su questo prototipo è:
durante lo scambio di dati se stacco il cavo ethernet arduino resta in timeout per circa 30 sec, fermando tutti i processi che riprendono al termine di questo tempo. E' chiaro che è normale e giusto che sia così, ma non posso permettermi che l'mcu aspetti.
Quindi il server resta aperto bisognerebbe chiuderlo ad ogni trasmissione indifferentemente che il messaggio sia arrivato o no.
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?

Ho cercato i timeout e non c'è sulla libreria WebSocket.h, ma non posso andare a toccare la w5100 o la ethernet.h comprometto tutto, devo trovare il modo di dare la possibilità alla ethernet di disconnetersi a suo piacimento, invece ora essa intercetta un
onConnect
onData
onDisconnect
se non gli arriva un disconnect da parte del client va in palla :sweat_smile:

ciao

Ho trovato questo che potrebbe essere interessante

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

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.

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.

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

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

#include <utility/w5100.h>

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

W5100.setRetransmissionTime(0x07D0);

W5100.setRetransmissionCount(3);




That gives me a 3 second timeout on a bad server connection.

x iscrizione

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

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

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

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

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

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)

alcuni socket hanno una porta assegnata senza ip

che siano "in ascolto" di una connessione?