Liaison TCPIP décalage de réception

Fermé
robunccm Messages postés 52 Date d'inscription jeudi 7 février 2019 Statut Membre Dernière intervention 9 mars 2024 - 28 nov. 2021 à 18:39
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 - 29 nov. 2021 à 17:35
Bonsoir à tous, j'en appelle une fois de plus à vos lumières pour tenter d'y voir plus clair.
Merci par avance.

Le contexte Un PC dialogue avec un Arduino via Ethernet.

Dans un premier temps le principe est plutôt simple.
Le PC envoi un ordre, l'Arduino retourne instantanément cet ordre en le complétant de diverses data.
Mon problème je ne reçoit
le retour de l'ordre 1 qu'après l'envoi de l'ordre 2,
le retour de l'ordre 2 qu'après l'envoi de l'ordre 3
et ainsi de suite.

Je n'ose pas vous dire le nombre de variante essayées mais sans succès!
Ce doit être gros comme une porte de grange mais je bute.

Merci de votre aide
Roland dit Le chef de gare


Déclaration data
        private TcpClient clientSocket17x = new TcpClient();


Ouverture d'un socket
        private void TryConnectClient(int _numARD)
{
try
{
string AdresseIP = "192.168.1." + Convert.ToString(ArdNum);
clientSocket17x.Connect(AdresseIP, 8000 + _numARD);
clientSocket17x.ReceiveBufferSize = 50;
//clientSocket17x.ReceiveTimeout = 5000;
}
catch (Exception exception)
{ MessageBox.Show("Rob Try ConnectClient" + exception.Message); }
}


Méthode Write et Read
        public void SendOrder(string Order)
{
NetworkStream serverStream = clientSocket17x.GetStream();
serverStream.Flush();
TxtLine2 = Order;
byte[] buffer = System.Text.Encoding.ASCII.GetBytes(Order + "\n");
serverStream.Write(buffer, 0, buffer.Length);
serverStream.Flush();
Int32 cpt = 0;
String rep = "";
if (serverStream.DataAvailable)
{
serverStream.Read(inStream, 0, clientSocket17x.ReceiveBufferSize);
string returndata = Encoding.ASCII.GetString(inStream);
TxtLine3 = returndata;
}
}




Configuration: Windows / Chrome 96.0.4664.45
A voir également:

3 réponses

Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
28 nov. 2021 à 19:29
Bonsoir

La seul fois où j'ai codé une liaison TCP, c'était dans un cadre particulier où il fallait utiliser une classe métier particulière (et donc pas TcpClient).

Mais en UDP et cette fois là, le dialogue n'est pas instantané.

Là comme je lis ton code (je me trompe peut-être), il faudrait que ça le soit, tu cherches à lire la réponse sans même attendre qu'elle soit arrivé.
Tu pourrais peut-être faire une boucle le temps que serverStream.DataAvailable passe à true (avec un nombre max de boucle sinon en cas de coupure de liaison ça fera une boucle infinie).
Ça va figer ton thread, mais ça permettra de voir si mon hypothèse est juste.

Un truc du genre
for(int i = 0; i < 1000; i++)
{
    if(serverStream.DataAvailable)
         break;
    Thread.Sleep(1);
}


En plus, tu te sers 2 fois de la méthode Flush(), dans les exemples que j'ai trouvé, cette méthode n'est pas utilisée.

1
robunccm Messages postés 52 Date d'inscription jeudi 7 février 2019 Statut Membre Dernière intervention 9 mars 2024 1
28 nov. 2021 à 19:34
Je soupçonne effectivement quelque chose de ce genre. Je vais tenter de le mettre en évidence avec ta proposition.
Quant à la méthode Flush il semble qu'elle ne soit pas encore implémentée et ne servirait à rien.
Je teste et je t'informe. En tout merci.
0
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 931
29 nov. 2021 à 17:35
C'est cool que tu aies trouvé.
Je ne pensais pas que Write était synchrone....

Pour éviter que ta fenêtre fige, tu peux mettre ce code dans un thread.
A la fin, il faut que tu signales que c'est fini, avec un évènement par exemple
1
robunccm Messages postés 52 Date d'inscription jeudi 7 février 2019 Statut Membre Dernière intervention 9 mars 2024 1
29 nov. 2021 à 11:19
Bonjour à tous et à Whismeril en particulier car fidèle à l'écoute de mes questions, merci une nouvelle fois.
Toutefois la proposition n'a pas fonctionné mais comme souvent elle m'a conduit d'autres test qui ont aboutis.
En réalité le problème se situait du coté Arduino qui construisait mal la réponse.

Voici le code finalement utilisé et sans doute perfectible.

Pour ce que j'en comprends.
Ce code gère une liaison dite bloquante ou synchrone, serverStream.Write se charge de l'envoi du message, dès l'envoi de celui-ci le processus se met en écoute et serverStream informé par serverStream.DataAvailable.Read se charge de la lecture de la réponse. On ne peut donc pas la manquer le problème est que si il n'y a pas de réponse le système attend indéfiniment. Il existe une possibilité de TimeOut.

Par ailleurs une alternative dite asynchrone évite le blocage, à priori elle est plus complexe . Mais à vaincre sans péril on triomphe sans gloire ... donc à bientôt pour le prochain épisode.

Roland


        public void SendOrder(string Order)
{
NetworkStream serverStream = clientSocket17x.GetStream();
TxtLine2 = Order;
byte[] buffer = System.Text.Encoding.ASCII.GetBytes(Order + "\n");
serverStream.Write(buffer, 0, buffer.Length);

if (serverStream.CanRead)
{
byte[] myReadBuffer = new byte[1024];
StringBuilder myCompleteMessage = new StringBuilder();
int numberOfBytesRead = 0;
do
{
numberOfBytesRead = serverStream.Read(myReadBuffer, 0, myReadBuffer.Length);
myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
}
while (serverStream.DataAvailable);
TxtLine3 = (myCompleteMessage.ToString());
}
else
{
TxtLine3 = ("Sorry. You cannot read from this NetworkStream.");
}

}
0