Bonjour,

J'ai un Arduino qui fonctionne en client web avec le shield Ethernet 2 Arduino officiel et la dernière version de la librairie Ethernet

Je suis en train de mettre au point mon programme.

J'ai analysé les échanges entre mon Arduino Client et le serveur avec Wireshark https://www.wireshark.org/

Dans mon code, j'envoie la requête au serveur avec deux instructions client.print() :

client.print(Requete);
client.print(FPSTR(Requete2));

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <SPI.h>
 
// DALLE TACTILE ************************************************************************************************************************************************
// Calibration à faire avec 003_TFT_Touch_Calibrate_OK
#include "URTouch.h"
#define t_IRQ 5
#define t_MISO 7 // La broche 4 est utilisée pour le lecteur SD de l'ethernet Shield
#define t_MOSI 3
#define t_CS 2
#define t_SCK 1
URTouch ts(t_SCK, t_CS, t_MOSI, t_MISO, t_IRQ);
 
// ECRAN TFT ****************************************************************************************************************************************************
#include <PDQ_GFX.h>
#include "PDQ_ILI9341_config.h" // C'est dans le fichier PDQ_ILI9341_config.h qu'on définit les broches CS, DC et RST
#include <PDQ_ILI9341.h>  
PDQ_ILI9341 tft;      
#define TFT_PWM_LED 6 // Un transistor PNP permet de piloter le rétroéclairage de l'écran TFT
 
// ETHERNET *****************************************************************************************************************************************************
#include <Ethernet.h>
byte mac[] = {
  0xA8, 0x61, 0x0A, 0xAE, 0x75, 0xCA //Voir étiquette collée sous le Shield
};
IPAddress ip(192, 168, 123, 177); //Choisir une IP fixe compatible avec le réseau local ou bien utiliser DHCP
EthernetClient client;
byte serverIP[] = { 192, 168, 123, 32 }; // Adresse IP du PC Fixe
 
// VARIABLES GLOBALES *******************************************************************************************************************************************
 const char Requete2[] PROGMEM = " HTTP/1.1\r\nHost:\r\nConnection: close\r\n\r\n";
 #define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
 
char Buffer_DispXY[15];
char Requete[50];
char WebPage[300];
 
// SETUP ********************************************************************************************************************************************************
void setup() {
  analogWrite(TFT_PWM_LED,128);
 
  tft.begin();
  tft.setRotation(0);
 
  ts.InitTouch(PORTRAIT);
  ts.setPrecision(PREC_EXTREME);
  tft.fillScreen(ILI9341_BLACK);
 
  tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
  tft.setTextSize(2);
 
  // You can use Ethernet.init(CSpin) to configure the CS pin
  //Ethernet.begin(mac, ip, myDns, gateway); //Pas besoin de spécifier le DNS et le GATEWAY si on se contente d'échanger avec un serveur local dont on connait l'IP
  Ethernet.begin(mac, ip);
 
  tft.setCursor(0, 25);
  tft.print(F("PRET  "));
}
 
// LOOP *********************************************************************************************************************************************************
void loop() {
    int retro;
    int x, y;
    int nb;
    char c;
    int i;
    unsigned long debut; //gestion timeout serveur
    unsigned long duree; //mesure durée communication Ethernet
    unsigned long duree2; //mesure durée gestion écran
 
   // On demande à l'écran tactile s'il y a eu un appui :
    if (ts.dataAvailable()) {
      duree2=millis();
      ts.read();
      x = ts.getX();
      y = ts.getY();
 
      if ((x != -1) && (y != -1)) {
        // Le rétroéclairage, que l'on règle en fonction de la position tapée à l'écran tactile :
        retro=y-10;
        if (retro<0) {retro=0;}
        if (retro>255) {retro=255;}
        analogWrite(TFT_PWM_LED,retro);
 
        // Affichage des coordonnées à l'écran :
        snprintf_P(Buffer_DispXY, sizeof(Buffer_DispXY), PSTR("X=%3d Y=%3d"), x, y);
        tft.fillScreen(ILI9341_BLACK);
        tft.setCursor(55, 5);
        tft.print(Buffer_DispXY);
 
        duree=millis();
 
        // Connection au serveur web :
        // client.stop(); // L'arrêt du client prend beaucoup de temps, à faire après
        if (client.connect(serverIP, 80)) {
 
		  //On fait la requête au serveur, en mettant dans l'URL les coordonnées tapées à l'écran tactile :
          snprintf_P(Requete, sizeof(Requete), PSTR("GET /?X=%d&Y=%d"), x, y);
          client.print(Requete);
          client.print(FPSTR(Requete2));
 
          //Attente de la page web
          debut = millis();
          nb=0;
          while(nb==0){ 
            nb = client.available();
            if (millis()-debut>2000) {break;} //Timeout indispensable sinon on bloque l'Arduino en cas de problème serveur
          }
 
          //Lecture de la page web et affichage
          if (nb==0) {
            tft.setCursor(0, 25);
            tft.print(F("TIMEOUT"));
          } else {
            //On cherche le début de la page, pour zapper la réponse HTTP :
            c=" ";
            while(c!='<'){ 
              c=client.read();
              nb--;
            }
            WebPage[0]=c;
            for (i=1;i<=nb;i++) {
              WebPage[i]=client.read();
              if (i>298) {break;} // Sécurité pour éviter un buffer overflow
            }
            // La chaine doit se terminer par un octet nul pour utilisation avec tft.print()
            WebPage[i]=0; // (normalement i+1 mais il y un saut de ligne à éliminer)
 
            tft.setCursor(160, 25);
            duree = millis()-duree;
            tft.print(duree); // Affichage du temps pris pour envoyer la requête au serveur et recevoir la réponse
            tft.print(F("ms"));
 
            tft.setCursor(0, 45);
            tft.print(WebPage);
 
            tft.setCursor(0, 25);
            tft.print(F("OK"));
 
            tft.setCursor(80, 25);
            tft.print(millis()-duree2-duree);  // Affichage du temps pris pour gérer l'appui sur l'écran tactile et l'affichage
            tft.print(F("ms"));
          }
        } else {
          tft.setCursor(0, 25);
          tft.print(F("ERREUR"));
        }
        //client.stop(); //L'arrêt du client prend beaucoup de temps (entre 1000ms et 1400ms) et ne sert à rien !
      }
  }
}
Problème : en analysant le traffic TCP/IP avec Wireshark, je vois que mon Arduino envoie un premier paquet contenant 16 caractères utiles, et tout le reste sous forme de paquets avec un seul octet.
C'est de la communication lettre par lettre , sachant que chaque paquet fait 60 octets, le rendement est pas terrible De plus cela oblige le serveur à envoyer plusieurs accusés de réception.

Le serveur (sur mon PC, créé en VB.NET avec HttpListener) lui envoie sa réponse d'un seul bloc (un paquet de 230 octets environ)

Curieusement, sur mon Arduino, entre l’envoi de la requête et la réception du dernier octet de la page web envoyé par le serveur il ne se passe que 23 millisecondes, donc c'est quand même rapide

Mais ce n'est pas normal que la requête soit envoyée de façon si fragmentée.

Ce que je ne comprend pas c'est que j'ai pris la précaution d'envoyer ma requête avec juste deux instructions client.print(), aussi je ne devrais avoir que deux paquets et pas des dizaines de paquets

Petite remarque : dans mon programme j'ai commenté l'instruction client.stop(), elle fait perdre entre 1000ms et 1400ms, et elle ne sert à rien.

A bientôt