Go Down

Topic: Accettare più connessioni in ingresso su server ethernet (Read 11748 times) previous topic - next topic

lestofante

lacia perdere quetsa idea di avere due EthernetServer, crea solo casino.

Il problema potrebbe esseer che nonostante l'ethernet shield possa avere più client, la libreria non sia stat sviluppata di conseguenza...
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

Janos

E' quello che avevo pensato anche io, ma così facendo è un bel casino...  =( =( =( =( =( =(

Janos

Ma cosa si intende per socket? Cos'è? Se socket = porta sono fregato...

lestofante

no, leggiti qualcosa sui socket su wikipedia, una porta può evere più socket, in pratica è il gestore di flusso tra due host
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

pablos71

Janos io non ti capisco... sono 2 settimane che ti disperi su questo forum. Apri 2 treadh al giorno quasi e +/- chiedi le stesse cose... fanne uno e continua quello.  :smiley-eek:

Ora se tu dicessi vorrei fare questo quello  e quell'altro con parole tue, sarebbe più facile.
Ho una pagina web vorrei che quando si collega uno blabla, quando si collega un altro bla bla.... Con richieste scritte così non finirai mai il tuo progetto te lo garantisco, fai degli esempi.
L'esperienza è il tipo di insegnante più difficile ....
Prima ti fa l'esame e poi ti spiega la lezione.

Janos


Janos io non ti capisco... sono 2 settimane che ti disperi su questo forum. Apri 2 treadh al giorno quasi e +/- chiedi le stesse cose... fanne uno e continua quello.  :smiley-eek:

Ora se tu dicessi vorrei fare questo quello  e quell'altro con parole tue, sarebbe più facile.
Ho una pagina web vorrei che quando si collega uno blabla, quando si collega un altro bla bla.... Con richieste scritte così non finirai mai il tuo progetto te lo garantisco, fai degli esempi.

http://arduino.cc/forum/index.php/topic,153773.msg1153068.html#msg1153068
Sto creando una libreria per gestire una comunicazione ModbusTCP. Anzi, ne sto creando due, una per gestire la comunicazione ModbusTCP lato server e una per il lato client. Le informazioni che sto chiedendo sono perché cercando a giro non ho trovato risposta, vedi che deve essere messo a HIGH il pin 4 per non far bloccare la shield quando si inserisce una SD (dove altro avrei potuto chiederlo? e per di più, serviva sapere che sto facendo una libreria per modbus per avere una risposta?), oppure che non si riesce a ricevere dati da client diversi sulla stessa porta. E comunque, quando trovo una soluzione da solo l'ho comunque condivisa con il resto del forum (http://arduino.cc/forum/index.php/topic,153590.msg1152899.html#msg1152899), che anche per questo esempio non era spiegato granché bene come fare, quindi se mi spieghi cosa sto facendo di male per il forum (anzi, se me lo fai dire da un mod) la smetto qui...

P.S. Che post dovrei aprire? "Tutti i problemi di Janos..."? Apro un post per ogni argomento, no?

Janos

Tornando in topic, riporto qui la funzione server.available() presa dal file EthernetServer.cpp:

Code: [Select]
EthernetClient EthernetServer::available()
{
  accept();

  for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
    EthernetClient client(sock);
    if (EthernetClass::_server_port[sock] == _port &&
        (client.status() == SnSR::ESTABLISHED ||
         client.status() == SnSR::CLOSE_WAIT)) {
      if (client.available()) {
        // XXX: don't always pick the lowest numbered socket.
        return client;
      }
    }
  }

  return EthernetClient(MAX_SOCK_NUM);
}


Se aggiungessi un metodo alla classe per testare il singolo socket invece di cercare fra tutti i socket? Ovvero così:

Code: [Select]
EthernetClient EthernetServer::available(uint8_t socket)
{
  accept();

  EthernetClient client(socket);
  if (EthernetClass::_server_port[socket] == _port &&
      (client.status() == SnSR::ESTABLISHED ||
       client.status() == SnSR::CLOSE_WAIT)) {
    if (client.available()) {
      // XXX: don't always pick the lowest numbered socket.
      return client;
    }
  }

  return EthernetClient(MAX_SOCK_NUM);
}


Potrebbe funzionare? Purtruppo non ho l'Arduino a disposizione...

Janos

FUNZIONA!!!!!!!!!!!!!!!!

A chi potesse interessare, ecco i file modificati. Li ho presi dall'IDE 1.5.2 dalla sezione per AVR.

Il metodo che ho incluso è:

Code: [Select]
server.available(uint8_t socket)

Con il quale è possibile verificare se un client è collegato ad uno specifico socket. Qui di seguito riporto anche la modifica fatta alla classe EthernetServer:

Code: [Select]
EthernetClient EthernetServer::available(uint8_t socket)
{
  accept(socket);

  if (socket < MAX_SOCK_NUM) {
    EthernetClient client(socket);
    if (EthernetClass::_server_port[socket] == _port &&
        (client.status() == SnSR::ESTABLISHED ||
         client.status() == SnSR::CLOSE_WAIT)) {
      if (client.available()) {
        // XXX: don't always pick the lowest numbered socket.
        return client;
      }
    }
  }

  return EthernetClient(MAX_SOCK_NUM);
}


Ho dovuto aggiungere anche la funzione privata accept(unit8_t socket), qui di seguito ne riporto il codice:

Code: [Select]
void EthernetServer::accept(uint8_t socket)
{
  int listening = 0;

  if (socket < MAX_SOCK_NUM) {
    EthernetClient client(socket);

    if (EthernetClass::_server_port[socket] == _port) {
      if (client.status() == SnSR::LISTEN) {
        listening = 1;
      }
      else if (client.status() == SnSR::CLOSE_WAIT && !client.available()) {
        client.stop();
      }
    }
  }

  if (!listening) {
    begin();
  }
}

lestofante

#23
Mar 15, 2013, 11:08 am Last Edit: Mar 15, 2013, 11:15 am by lesto Reason: 1
capisco, available ritorna SEMPRE il primo client trovato in stato connesso o in attesa di chiusura di connessione. ciò vuol dire che ritorna sempre il primo client.

Quindi in realtà io farei una cosa differente: una flag in EthernetClient, che di default è a false.

Quando l'available cerca un client, lo cerca con la flag a false, e prima di ritornarlo mette la flag a true. In questo modo NON giochi con i socket lato sketch, la modifica è molto meno evidente (una flag pubblica in EthernetCliente una condizione in più nell'if del server available)

ps. in realtà lui prima di ritornare il client fa
Code: [Select]
if (client.available()) {
ciò vuol dire che ottenuto un client, prima svuoti il suo buffer di lettura e POI fai un altra available...

quindi SENZA modifiche alle liobrerie, riadatto il mio codice che hai riadattato :)

Code: [Select]
#define NUMERO_CLIENT 4

#include <Ethernet.h>
#include <SPI.h>

EthernetClient client[NUMERO_CLIENT];
EthernetServer server(502);
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x97, 0xFB };
IPAddress ip(10,10,10,157);

void setup() {
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);
  Ethernet.begin(mac, ip);
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  Serial.begin(115200);
};

void loop(){
EthernetClient temp = server.available();
for (int i=0;i<NUMERO_CLIENT;i++){
   if ( NULL != client[i] || client[i]){
       while (client[i].available()) {
          Serial.print(client[i].read());
       }
       if (!client[i].connected()) client[i] = NULL;
   }else{
       //trovato un posto vuoto, usalo per il nuovo client!
       client[i] = temp;

       //modifica di Lesto
       while (client[i].available()) {
         Serial.print(client[i].read());
       }
       //FINE modifica di Lesto

       temp=server.available(); //accetta l'eventuale prossima connessione
       if (temp) {
         Serial.print("Client ");
         Serial.print(i+1);
         Serial.println(" connesso");
       };
   }
}
}


però in realtà resta il richio che tra la while che svuota i caratteri e la prossima available() arrivi un carattere e tutto salti di nuovo... bel casino! provo ad aprire un issue
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

PaoloP


Lesto, sei la mia unica speranza....  =( =( =(


Aiutami, Obi Wan Kenobi, sei la nostra unica speranza...  :smiley-mr-green: :smiley-mr-green: :smiley-mr-green:

lestofante



Lesto, sei la mia unica speranza....  =( =( =(


Aiutami, Obi Wan Kenobi, sei la nostra unica speranza...  :smiley-mr-green: :smiley-mr-green: :smiley-mr-green:


come to the dark side... we have cookies!

(ho pesantemente editato il mio intervento precedente)
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

Janos

#26
Mar 15, 2013, 11:17 am Last Edit: Mar 15, 2013, 11:19 am by Janos Reason: 1

Aiutami, Obi Wan Kenobi, sei la nostra unica speranza...  :smiley-mr-green: :smiley-mr-green: :smiley-mr-green:
:smiley-sweat: :smiley-sweat: :smiley-sweat:

@lesto
Ci avevo pensato anche io ai flag ma così facendo mi tocca modificare di più la libreria, no? Devo settare il flag quando la server.available trova una connessione, ma non mi fidavo tanto su quando resettarlo... Ho visto che non è proprio banale tutta la gestione ed ho voluto essere il meno invasivo possibile...

Dopo opportuno degub sarebbe interessante se gli sviluppatori dell'IDE prendessero in considerazione la mia soluzione o una equivalente, altrimenti è impossibile accettare connessioni da più client...

lestofante

https://github.com/arduino/Arduino/issues/1320
aperto un issue, ho proposto:
1. il metodo available + flag
2. il metodo available + indice del socket da user
3. il metodo 1. ma in una funzione differente (per non rompere i vecchi codici)
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

Janos

Si si, quello che ho fatto io è un overload della funzione esistete, non ho modificato quella che gia c'è...  ;)

pablos71

Ma non riesci a fare più connessioni simultanee senza modificare la lib?
Di norma i bus hanno un identificativo per riconoscere chi fa la richiesta e quindi distinguerli.

Perchè questa modifica, a cosa serve ?
L'esperienza è il tipo di insegnante più difficile ....
Prima ti fa l'esame e poi ti spiega la lezione.

Go Up