Pages: [1] 2   Go Down
Author Topic: [Shield WiFi] La connessione TCP si interrompe dopo alcuni secondi di inattività  (Read 2488 times)
0 Members and 1 Guest are viewing this topic.
Bologna, Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salve a tutti,
è il mio primissimo post su questo forum e mi auguro di aver letto e compreso tutte le regole, in caso contrario provvederò a modificare il messaggio di conseguenza.

Premetto che, pur avendo un po' di esperienza nel campo della programmazione, sono assolutamente alle prime armi con Arduino quindi spero di azzeccare tutti i termini del caso...

Board in uso: Arduino Leonardo
Shield: WiFi Shield (Ufficiale Arduino)
Librerie SW aggiuntive: WiFi (Ufficiali Arduino)

Quello che vi sottopongo non è realmente un problema, ma più una domanda su TCP e sulla sua implementazione su Arduino visto che in passato ho lavorato solo con protocolli a livello più alto e non mi sono mai posto questi problemi: ho provato a connettermi ad un mio server TCP (Node.js) e la connessione sembra funzionare senza problemi. Posso trasferire dati in entrambe le direzioni, la cosa che mi ha spiazzato è che, contrariamente a quanto accade con altri client connessi al server, l'Arduino sembra chiudere la connessione dopo alcuni secondi di inattività e da quel momento naturalmente non posso inviare/ricevere nulla se non riconnettendomi al server.

Questo è normale o sbaglio qualcosa? Avevo pensato di inviare ciclicamente (dal server verso i client) una sorta di heartbeat che mantenesse in vita la connessione, ma non vorrei generare traffico inutile visto che i client software non presentano lo stesso problema!

Incollo il codice che sto utilizzando eliminando le parti relative alla connessione WiFi perchè sono esattamente le stesse di qualsiasi esempio contenuto nella libreria:
Code:
#include <SPI.h>
#include <WiFi.h>

// ...WiFi Variables...
WiFiClient client;

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
 
  // ...WiFi Connection...
 
  Serial.println("\nStarting connection to server...");
  if (client.connect(server, port)) {
    Serial.println("connected to server");
  }
}

void loop() {
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  while (Serial.available() > 0) {
    char inChar = Serial.read();
    if (client.connected()) {
      client.print(inChar);
    }
  }
 
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    // do nothing:
    while(true);
  }
}

// ...WiFi Custom Functions...

Probabilmente la mia sarà una domanda stupida ma non sono riuscito a trovare una risposta da nessuna parte! smiley-sad

Grazie dell'attenzione.
Marco Lipparini
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10501
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

dipende a che servizio ti stai collegando, ma se di pubblico dominio (onternet) è normalissimo. A priori molte implementazioni TCP chiudono la connessione qunado inattiva, il parametro si chiama timeout, oppure keep-alive. che poi keep-alive viene usato anche come nome per l'implementazione di inviare un messaggio ogni tot appunto per tenere in vita la comunicazione

se hai ipostato gli eventuali time-out sia sull'arduino che magari su un programmino che ti fai tu e la connessione continua a cadere (o non rispetta i tempi), allora facci sapere che c'è qualcosa di più grave

per verificare i tempi, puoi provare a collegarti via telnet al servizio, e verificare se i tempi di time-out sono uguali a quelli di arduino
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Bologna, Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Dunque... intanto grazie per la risposta, vediamo se riesco ad aggiungere qualche informazione utile:
Da quel che leggo dalla documentazione di Node.js (link a fine post) i socket di default non hanno timeout e il "keep-alive" (quello originale di TCP, ovvero un pacchetto vuoto e non un'implementazione personalizzata) non è attivo.
Ho modificato il server attivando il "keep-alive" per tutti i socket in entrata e impostandogli un delay dall'ultimo pacchetto ricevuto di 100ms, ma la situazione non cambia... dopo qualche secondo dall'ultimo pacchetto ricevuto/inviato dall'Arduino mi viene comunicato tramite console: "disconnecting.".

NB: Una cosa strana che ho notato solo ora è che Arduino mi segnala la connessione come chiusa (ed effettivamente non posso più trasmettere dati in nessuna direzione), però il server non si accorge minimamente della chiusura fino al primo tentativo di scrittura/lettura.
Descrivo un attimo questa cosa per chiarire la dinamica:
Praticamente ho uno o più client connessi e il server fa un broadcast dei messaggi ricevuti su tutti i client (eccetto l'autore del messaggio)... sostanzialmente è una chat minimale che sto usando per imparare.
  • Due client si connettono. (un terminale con comando "telnet" e un Arduino)
  • I client si scambiano messaggi con una frequenza tale da mantenere in vita la connessione con l'Arduino. (fin qui tutto regolare)
  • Ad un certo punto lascio cadere volutamente la connessione di Arduino.
  • Invio un nuovo messaggio dal client "telnet".
  • Il server va in crash lamentandosi del fatto che sto cercando di scrivere su un socket ormai chiuso.
Naturalmente questo non si verifica se a disconnettersi (anche in maniera brutale) è un client diverso da Arduino perchè ho programmato il server in modo che cancelli i socket dalla lista di broadcast appena viene rilevata la chiusura.

Come test aggiuntivi posso dire che tramite comando "telnet" da una macchina remota verso il server la connessione si stabilisce senza problemi e senza interruzioni... naturalmente anche i messaggi trasmessi viaggiano senza errori. Lo stesso discorso vale anche per un piccolo client che ho scritto in Node.js giusto per avere un'ulteriore conferma: anche in questo caso la connessione viene mantenuta fino ad interruzione *manuale*.

Link utili:
http://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback

P.S.
Dimenticavo: non ho idea di come impostare tempi di timeout o la funzionalità keep-alive dal codice sull'Arduino, ho guardato la documentazione ma non ho trovato nulla a riguardo quindi non posso assolutamente escludere che si tratti anche di questo!
« Last Edit: August 28, 2012, 11:53:34 am by Liarco » Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10501
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
NB: Una cosa strana che ho notato solo ora è che Arduino mi segnala la connessione come chiusa (ed effettivamente non posso più trasmettere dati in nessuna direzione), però il server non si accorge minimamente della chiusura fino al primo tentativo di scrittura/lettura.

questo è normale se una delle due parti si disconnette senza inviare il debito messaggio di chiusura, nulla di preoccupante se non che arduino non si sta comportando bene, anzi...
probabilmente possiede qualche time-out interno e non riescie a gestire i keep-alive o qualcosa del genere... che chip ha la tua ethernet shield?

hai un software tipo wireshark così da analizzare il traffico TCP/UDP?
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Bologna, Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In realtà, come ho scritto nel primo post, non si tratta dell'Ethernet Shield ma del WiFi Shield ufficiale: http://arduino.cc/en/Main/ArduinoWiFiShield

Per quanto riguarda l'analisi del traffico mi informo su come si utilizza wireshark e provo a fornirti un resoconto perchè da solo probabilmente non saprei come interpretarlo... se ho capito bene devo analizzare il traffico sulla mia macchina linux (server) per capire se il comportamento anomalo può derivare dalla comunicazione client/server, altrimenti potrebbe essere semplicemente un intoppo nella libreria WiFi?

Inoltre c'è da dire che la libreria WiFi l'ho scaricata dal sito ufficiale, ma c'è scritto chiaramente che verrà inclusa nel core solo in una prossima versione dell'IDE... non vorrei che fosse ancora in fase di sviluppo!
Quote
The WiFi Library will be included in a future release of the Arduino IDE. You can download the most recent version, and install it as you would any other library.

Fonte: http://arduino.cc/en/Guide/ArduinoWiFiShield
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10501
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

no, è che la versione attuale semplicemente è antecedente alla wifi shield.. che però è molto nuova, quindi potrebbe avere qualche intoppo.

con wireshark iniziamo a capire dove ricercare il problema, anche se ad occhio c'è qualche timeout da parte di arduino
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Bologna, Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Allego il resoconto della sniffata fatta con wireshark, ho ristretto il campo coinvolgendo solo i risultati che includevano l'IP dell'Arduino in modo da evitare di raccogliere troppi dati inutili.

Il codice dell'Arduino è semplicemente quello che ho postato sopra con l'aggiunta di una riga di scrittura aggiuntiva usata come debug:
Code:
client.println("Hi!");
Questa riga viene eseguita appena connesso al server.

Il server invece è molto semplice ed esordisce con un messaggio di benvenuto all'inizio di ogni nuova connessione.
Praticamente all'evento di connessione eseguo:
Code:
socket.write('Welcome to the Telnet server!\n');

La "cattura" con wireshark va dal momento in cui carico lo sketch sull'Arduino fino al momento della disconnessione automatica del dispositivo... l'ultimo pacchetto registrato arriva praticamente nello stesso momento in cui mi compare la scritta "disconnecting." nella console di Arduino.

* ArduinoWifi_wireshark_capture (0.98 KB - downloaded 20 times.)
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10501
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

non posso vedere i log perchè sono a lavoro, ma un amico che li ha analizzati mi dice che dopo  12 secondi che arduino dice "hi", invia un reset della connessione. Quindi il time-out è lato arduino.

dal Reference pare non esista un metodo per settare il time-out, quindi probabilmente è hard-codato nella libreria
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Bologna, Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Infatti anche a me sembrava così, però non so esattamente cosa sia il reset... perchè se fosse la richiesta di chiusura della connessione il mio server dovrebbe accorgersene come fa per tutti gli altri client, no?

Ad ogni modo sto provando ad analizzare il sorgente della libreria, non ci sto capendo molto, ma se trovo qualcosa di sospetto lo segnalo qui! smiley-wink
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10501
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

attento, il reset di connessione non è la stessa cosa di una chiusura connessione
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Bologna, Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nada, non sono ancora riuscito a tirarci fuori nulla... nella libreria non trovo riferimenti a questo timeout fantasma, ma probabilmente sono anche io che non la riesco a leggere completamente!

Temo di essermi arenato! smiley-sad

Nessuna novità dall'analisi con wireshark? (nessuna fretta eh, è giusto per sapere se hai ancora qualche freccia al tuo arco! smiley-wink)
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10501
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

no, noin c'è altro da tirar fuori
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Bologna, Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Può essere il caso di segnalare questa cosa o devo adeguarmi io e rassegnarmi a mandare un pacchetto ogni tanto per risvegliare la connessione? smiley-sad

P.S. Se devo segnalarlo, sapresti indicarmi il modo più adeguato?

Intanto grazie mille per tutto, sei stato gentilissimo! smiley-wink
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10501
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

non so se funziona il trucco di inviare il messaggio. Apri un ticket su github https://github.com/arduino/Arduino
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 114
Posts: 7205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Certo che ti sei andato a infilare in un bel tunnel.  smiley-mr-green
Leonardo: scheda nuova
WiFi Shield: ancora più nuova
Librerie Wifi: nuovissime.  smiley-sweat

In questi casi un bug può essere sempre in agguato.  smiley-red
Logged

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

Pages: [1] 2   Go Up
Jump to: