IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Portée des variables


Sujet :

Langage Perl

  1. #1
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    272
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 272
    Points : 166
    Points
    166
    Par défaut Portée des variables
    Bonjour,

    J'essaye d'écrire un serveur/client UDP, et j'ai un petit problème, voici le source du serveur:

    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
    #!/usr/bin/perl -w
     
    use strict;
    use IO::Socket;
     
    my($sock);
    my($newmsg);
    my($port);
    my($ipaddr);
    my($arret);
    my($boucle);
    my($x);
    my($y);
    my($dir);
    my($MAXLEN);
    my($PORTNO);
     
    $arret = 0;
    $boucle = 0;
    $x = 0;
    $y = 0;
    $dir = 0;
    $MAXLEN = 20;
    $PORTNO = 1027;
     
    $sock = IO::Socket::INET->new( LocalPort => $PORTNO, Proto => 'udp') or die "socket: $@";
     
    print "Serveur demarre sur port $PORTNO\n";
     
    while ( $arret == 0 )
    {
    	if ( $sock->recv( $newmsg, $MAXLEN ,MSG_DONTWAIT ) )
    	{
    		($port,$ipaddr) = sockaddr_in($sock->peername);
    		print "Recu $newmsg\n";
    		if ( $newmsg =~ "^GO+" )
    		{
    			$boucle = 1;
    		}
    	}
    	if ( $boucle == 1 )
    	{
    		if ( $dir == 0 )
    		{
    			if ( $x == 100 )
    			{
    				$y++;
    				if ( $y == 100 )
    				{
    					$dir = 1;
    				}
    			}
    			else
    			{
    				$x++;
    			}
    		}
    		else
    		{
    			if ( $x == 0 )
    			{
    				$y--;
    				if ( $y == 0 )
    				{
    					$dir = 0;
    				}
    			}
    			else
    			{
    				$x--;
    			}
    		}
    		$sock->send( $ipaddr.";".$x.";".$y."\0\n" );
    		sleep ( 1 );
    	}
    } 
    die "recv: $!";
    et le source du client:

    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
    #!/usr/bin/perl -w
     
    use IO::Socket;
    use strict;
     
    my($sock, $msg, $port, $ipaddr, $hishost, $MAXLEN, $PORTNO, $TIMEOUT);
     
    $MAXLEN  = 1024;
    $PORTNO  = 1027;
    $TIMEOUT = 5;
     
    $sock = IO::Socket::INET->new(Proto => 'udp', PeerPort => $PORTNO, PeerAddr => 'localhost') or die "Creating socket: $!\n";
     
    $sock->send("GO") or die "send: $!";
     
    while ($sock->recv($msg, $MAXLEN))
    {
    	print "$msg\n";
    } 
    die "recv: $!";
    Petit problème, à l'exécution j'ai l'erreur suivante coté serveur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Serveur demarre sur port 1027
    Recu GO
    send: Cannot determine peer address at ./serveur.pl line 73
    J'ai l'impression que la variable $sock n'est pas initialisée à la ligne 73 (dans le send) alors qu'elle l'est ligne 32 (dans le recv). Je pense donc à un problème de portée de variable mais je ne sais pas comment rendre $sock globale, d'autant que "use strict;" m'oblige à les déclarer en my(...).

    Merci d'avance pour votre aide.

    Cordialement.

  2. #2
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    $sock me semble avoir la bonne portée.

    Edit : commentaire supprimé, je pense que c'était une bêtise.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  3. #3
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    As-tu essayé 127.0.0.1 à la place de localhost comme PeerAddr dans le client ?

    Edit :
    Mmmh... ça me semble à nouveau une bêtise...
    désolé
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  4. #4
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Ajoute $ipaddr et $port dans ce print :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print "Recu $newmsg\n";
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  5. #5
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    272
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 272
    Points : 166
    Points
    166
    Par défaut 2eme passage
    Re,

    Les variables $ipaddr, $port, $sock sont tous égal à quelque chose.
    Par contre le send se fait bien la première fois, c'est lors du deuxième passage que j'ai l'erreur.
    Lors de ce deuxième passage, je ne rentre pas dans la boucle:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if ( $sc->recv( $newmsg, $MAXLEN ,MSG_DONTWAIT ) )
    { ...
    }
    Cela influence-t-il $sock ?

    Merci de vos réponses, cordialement.

  6. #6
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Oui, en fait, ça me semble normal, puisque tu utilises l'option DONTWAIT, donc même s'il n'y a aucun message à lire, on ne rentre pas dans le if, et comme on a position $boucle à un précédemment, on rentre dans la boucle.
    Essaye en plaçant le if ( $boucle == 1 ) dans la bloc du if ( $sock->recv( $newmsg, $MAXLEN ,MSG_DONTWAIT ) )
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  7. #7
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    272
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 272
    Points : 166
    Points
    166
    Par défaut Pas compris la...
    Re,

    J'ai mis le MSG_DONTWAIT pour éviter de bloquer sur le recv. En fait mon programme reçoit "GO", à partir de ce moment il doit envoyer le message toutes les secondes jusqu'à ce qu'il reçoive "STOP" en ajoutant dans le if du recv:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if ( $newmsg =~ "^STOP+" )
    {
    	$boucle = 0;
    }
    Pourquoi et ou mettre un

    dans le if du recv ?

    Je ne sais pas ce qu'il "perd" dans $sock entre la première et la seconde itération quand il arrive au send.

    Cordialement.

  8. #8
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    272
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 272
    Points : 166
    Points
    166
    Par défaut recv pose probleme
    Re,

    En fait c'est le recv qui pose problème quand il n'y a rien a recevoir. J'ai modifié mon code comme suis, et la ça marche, mais cela ne m'arrange pas car je ne peut plus envoyer de message au serveur:

    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
    #!/usr/bin/perl -w
     
    use strict;
    use IO::Socket;
     
    my($sc, $newmsg, $port, $ipaddr, $arret, $boucle, $x, $y, $dir, $MAXLEN, $PORTNO, $nbBoucle);
     
    $arret = 0;
    $boucle = 0;
    $x = 0;
    $y = 0;
    $dir = 0;
    $MAXLEN = 20;
    $PORTNO = 1027;
     
    $sc = IO::Socket::INET->new( LocalPort => $PORTNO, Proto => 'udp') or die "socket: $@";
     
    print "[serveur.pl] Serveur demarre sur port $PORTNO\n";
     
    while ( $arret == 0 )
    {
    	if ( $boucle == 0 )
    	{
    		if ( $sc->recv( $newmsg, $MAXLEN, MSG_DONTWAIT ) )
    		{
    			($port,$ipaddr) = sockaddr_in($sc->peername);
    			print "[serveur.pl] ($port) ($ipaddr) Recu $newmsg\n";
    			if ( $newmsg =~ "^GO+" )
    			{
    				print "[serveur.pl] Demarrage boucle\n";
    				$boucle = 1;
    			}
    			if ( $newmsg =~ "^STOP+" )
    			{
    				print "[serveur.pl] Arret boucle\n";
    				$boucle = 0;
    				$nbBoucle = 5;
    			}
    		}
    	}
    	if ( $boucle == 1 )
    	{
    		if ( $dir == 0 )
    		{
    			if ( $x == 100 )
    			{
    				$y++;
    				if ( $y == 100 )
    				{
    					$dir = 1;
    				}
    			}
    			else
    			{
    				$x++;
    			}
    		}
    		else
    		{
    			if ( $x == 0 )
    			{
    				$y--;
    				if ( $y == 0 )
    				{
    					$dir = 0;
    				}
    			}
    			else
    			{
    				$x--;
    			}
    		}
    		$sc->send( $ipaddr.";".$x.";".$y."\0\n", 0, $sc->peername );
    		sleep ( 1 );
    	}
    } 
    die "recv: $!";
    Donc dans ce cas on ne fait qu'un recv, il récupère le "GO", met $boucle à 1 et les send s'enchaine toutes les secondes. Mais je ne fais plus de recv par la suite.

    Que peut bien modifier dans $sock le recv si il ne recoit pas de données pour que send ne fonctionne plus ?

    Cordialement.

  9. #9
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Ce que je pense à propos de ton code initial (celui du premier post) :
    - avec l'option MSG_DONTWAIT, le retour de recv est vrai à tout les coups
    - tant que tu ne reçois pas le GO, $boucle reste à zéro, et tu ne passes pas dans le send
    - dès que le GO arrive, tu actives les send avec $boucle = 1 et tu initialises $ipaddr et $port
    - mais alors, tu entres de nouveau régulièrement dans le if de recv comme tu re-initialises $ipaddr et $port à chaque fois... mais sans avoir reçu de message, il y a fort à parier qu'ils ne valent plus les valeurs correctes.

    C'est ce que je pressens (sans certitude, car je n'ai jamais joué avec les sockets), c'est pourquoi je te demandais au début, de mettre un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print "ipaddr=$ipaddr, port=$port\n";
    juste avant le send.
    Je ne pense pas que ce soit l'objet socket qui soit en cause.

    Essaye en conditionnant l'initialisation de $ipaddr et $port, comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ($port,$ipaddr) = sockaddr_in($sc->peername) if length $newmsg;
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  10. #10
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    272
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 272
    Points : 166
    Points
    166
    Par défaut Eh bien non !
    Bonjour,

    J'ai ajouter ton "if length $newmsg;" mais toujours le même problème, l'appel de recv sans qu'il y ai de message reçu fait planter un appel à send. Je pense que je devrais gérer les messages reçu dans un thread.

    Cordialement.

  11. #11
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    272
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 272
    Points : 166
    Points
    166
    Par défaut Pour info
    Voici le source complet du serveur UDP:

    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
    #!/usr/bin/perl -w
     
    use strict;
    use IO::Socket;
     
    my($sc, $newmsg, $port, $ipaddr, $arret, $boucle, $x, $y, $dir, $MAXLEN, $PORTNO, $nbBoucle);
     
    $arret = 0;
    $boucle = 0;
    $x = 0;
    $y = 0;
    $dir = 0;
    $MAXLEN = 20;
    $PORTNO = 1027;
    #$nbBoucle = 5;
     
    $sc = IO::Socket::INET->new( LocalPort => $PORTNO, Proto => 'udp') or die "socket: $@";
     
    print "[serveur.pl] Serveur demarre sur port $PORTNO\n";
     
    while ( $arret == 0 )
    {
    	if ( $sc->recv( $newmsg, $MAXLEN, MSG_DONTWAIT ) )
    	{
    		($port,$ipaddr) = sockaddr_in($sc->peername) if length $newmsg;
    		print "[serveur.pl] ($port) ($ipaddr) Recu $newmsg\n";
    		if ( $newmsg =~ "^GO+" )
    		{
    			print "[serveur.pl] Demarrage boucle\n";
    			$boucle = 1;
    		}
    		#if ( $newmsg =~ "^PING+" )
    		#{
    		#	print "[serveur.pl] PING recu\n";
    		#	$nbBoucle = 5;
    		#}
    		if ( $newmsg =~ "^STOP+" )
    		{
    			print "[serveur.pl] Arret boucle\n";
    			$boucle = 0;
    			$nbBoucle = 5;
    		}
    	}
     
    	if ( $boucle == 1 )
    	{
    		if ( $dir == 0 )
    		{
    			if ( $x == 100 )
    			{
    				$y++;
    				if ( $y == 100 )
    				{
    					$dir = 1;
    				}
    			}
    			else
    			{
    				$x++;
    			}
    		}
    		else
    		{
    			if ( $x == 0 )
    			{
    				$y--;
    				if ( $y == 0 )
    				{
    					$dir = 0;
    				}
    			}
    			else
    			{
    				$x--;
    			}
    		}
    		$sc->send( $ipaddr.";".$x.";".$y."\0\n", 0, $sc->peername );
    		sleep ( 1 );
    		#$nbBoucle--;
    		#if ( $nbBoucle == 0 )
    		#{
    		#	print "[serveur.pl] Boucle time out\n"; 
    		#	$boucle = 0;
    		#}
    	}
    } 
    die "recv: $!";
    et celui du client:

    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
    #!/usr/bin/perl -w
     
    use IO::Socket;
    use strict;
     
    my($sock, $msg, $port, $ipaddr, $hishost, $MAXLEN, $PORTNO, $TIMEOUT, $nbBoucle);
     
    $MAXLEN  = 1024;
    $PORTNO  = 1027;
    $TIMEOUT = 5;
    $nbBoucle = 3;
     
    $sock = IO::Socket::INET->new(Proto => 'udp', PeerPort => $PORTNO, PeerAddr => 'localhost') or die "Creating socket: $!\n";
     
    $sock->send("GO") or die "send: $!";
     
    while ($sock->recv($msg, $MAXLEN))
    {
    	print "[client.pl] $msg\n";
    	$nbBoucle--;
    	if ( $nbBoucle == 0 )
    	{
    		print "[client.pl] Envoi PING\n";
    		$sock->send("PING") or die "send: $!";
    		$nbBoucle = 3;	
    	}
    } 
    die "recv: $!";
    Je test le client et le serveur sous FreeBSD et Linux.

    Cordialement.

  12. #12
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Tu n'as pas exactement fait ce que je demandais : ajoute un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print "send avec ($port) ($ipaddr)\n"
    juste avant le send...
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  13. #13
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    272
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 272
    Points : 166
    Points
    166
    Par défaut Ajout print
    Bonjour,

    j'ai ajouté un "print" la:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    while ( $arret == 0 )
    {
    	if ( $sc->recv( $newmsg, $MAXLEN, MSG_DONTWAIT ) )
    	{
    		($port,$ipaddr) = sockaddr_in($sc->peername);
    		print "Apres recv ($port) ($ipaddr)\n";
    		print "[serveur.pl] Recu $newmsg\n";
    		if ( $newmsg =~ "^GO+" )
    		{ ...
    et la:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    print "Avant send ($port) ($ipaddr)\n";
    		$sc->send( $ipaddr.";".$x.";".$y."\0\n", 0, $sc->peername );
    		sleep ( 1 );
    	}
    }
    et j'obtiens:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ ./serveur.pl
    [serveur.pl] Serveur demarre sur port 1027
    Apres recv (9764) )
    [serveur.pl] Recu GO
    [serveur.pl] Demarrage boucle
    Avant send (9764) )
    Avant send (9764) )
    send: Cannot determine peer address at ./serveur.pl line 79
    C'est bizarre il m'affiche bien le $port mais la $ipaddr à l'air de me "bouffer" la '(' de ($ipaddr)...

    Sinon j'ai la même chose, à noter que c'est au second passage dans le send que cela plante, donc après être passé par un recv qui n'avait rien à lire.

    Cela semble être propre à Perl, j'ai fait l'équivalent en C:

    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
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <string.h>
     
    #define MAXLEN 20
    #define PORT 1027
    #define COMPTEUR 5
     
    int handleSocket;
     
    unsigned char commencePar( char *ligne, char *texte )
    {
    	if ( strlen( ligne ) < strlen( texte ) )
    		return( 0 );
    	while ( *texte != '\n' && *texte != '\0' )
    	{
    		if ( *ligne != *texte )
    			return( 0 );
    		ligne++;
    		texte++;
    	}
    	return( 1 );
    }
     
    void EcouteUDP()
    {
    	struct sockaddr_in serveurAdresse;
    	handleSocket = socket(AF_INET,SOCK_DGRAM,0);
    	bzero( &serveurAdresse, sizeof(serveurAdresse) );
    	serveurAdresse.sin_family = AF_INET;
    	serveurAdresse.sin_addr.s_addr=htonl(INADDR_ANY);
    	serveurAdresse.sin_port=htons(PORT);
    	fcntl( handleSocket, F_SETFL, FNONBLOCK | FASYNC );
    	bind( handleSocket, (struct sockaddr *)&serveurAdresse, sizeof(serveurAdresse) );
    }
     
    int main(int argc, char**argv)
    {
    	struct sockaddr_in clientAdresse;
    	int nbOctet, stop = 0, boucle = 0, nbBoucle = COMPTEUR;
    	int x = 0, y = 0, dir = 0;
    	char msg[MAXLEN];
    	socklen_t longueur;
    	EcouteUDP();
    	while ( stop == 0 )
    	{
    		longueur = sizeof(clientAdresse);
    		for ( nbOctet = 0; nbOctet < MAXLEN; nbOctet++ )
    		{
    			msg[nbOctet] = '\0';	
    		}
    		nbOctet = recvfrom( handleSocket, msg, MAXLEN, 0, (struct sockaddr *)&clientAdresse, &longueur );
    		if ( nbOctet > 0 )
    		{
    			if ( commencePar( msg, "GO" ) )
    				boucle = 1;
    			if ( commencePar( msg, "PING" ) )
    				nbBoucle = COMPTEUR;
    			if ( commencePar( msg, "STOP" ) )
    				boucle = 0;				
    		}
    		for ( nbOctet = 0; nbOctet < MAXLEN; nbOctet++ )
    		{
    			msg[nbOctet] = '\0';	
    		}
    		if ( boucle == 1 )
    		{
    			if ( dir == 0 )
    			{
    				if ( x == 100 )
    				{
    					y++;
    					if ( y == 100 )
    						dir = 1;
    				}
    				else
    					x++;
    				}
    			else
    			{
    				if ( x == 0 )
    				{
    					y--;
    					if ( y == 0 )
    						dir = 0;
    				}
    				else
    					x--;
    			}
    			sprintf( msg, "toto;%i;%i\0\n", x, y );
    			printf ( "Envoi [%s]\n", msg );
    			sleep ( 1 );
    			nbBoucle--;
    			if ( nbBoucle == 0 )
    			{
    				printf ( "[serveur.c] Boucle time out\n" ); 
    				boucle = 0;
    				nbBoucle = COMPTEUR;
    			}
    		}
    	}
    }
    Et je n'ai pas de problème.

    Cordialement.

  14. #14
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    En lisant la doc de sockaddr_in (en fait, unpack_sockaddr_in qui est la méthode utilisée dans le cas d'un contexte de liste, comme dans ton programme), il est indiqué que l'adresse IP est fournie sous forme d' "an opaque string representing the IP address". Il est indiqué que pour l'afficher, il faut utiliser inet_ntoa :
    Citation Envoyé par perldoc socket
    sockaddr_in SOCKADDR_IN

    In a list context, unpacks its SOCKADDR_IN argument and returns an array consisting of (PORT, ADDRESS). In a scalar context, packs its (PORT, ADDRESS) arguments as a SOCKADDR_IN and returns it. If this is confusing, use pack_sockaddr_in() and unpack_sockaddr_in() explicitly.

    pack_sockaddr_in PORT, IP_ADDRESS

    Takes two arguments, a port number and an opaque string, IP_ADDRESS (as returned by inet_aton(), or a v-string). Returns the sockaddr_in structure with those arguments packed in with AF_INET filled in. For Internet domain sockets, this structure is normally what you need for the arguments in bind(), connect(), and send(), and is also returned by getpeername(), getsockname() and recv().

    unpack_sockaddr_in SOCKADDR_IN

    Takes a sockaddr_in structure (as returned by pack_sockaddr_in()) and returns an array of two elements: the port and an opaque string representing the IP address (you can use inet_ntoa() to convert the address to the four-dotted numeric format). Will croak if the structure does not have AF_INET in the right place.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

Discussions similaires

  1. Réponses: 8
    Dernier message: 17/02/2005, 09h05
  2. [FLASH MX] Portée des variables ???
    Par mic79 dans le forum Flash
    Réponses: 2
    Dernier message: 08/02/2005, 10h21
  3. Portée des variables vbscript vers ASP
    Par Immobilis dans le forum ASP
    Réponses: 3
    Dernier message: 03/11/2004, 10h14
  4. [XSL]Problème de portée des variables
    Par djulesp dans le forum XSL/XSLT/XPATH
    Réponses: 6
    Dernier message: 17/09/2004, 10h34
  5. [Portée] portée des variables
    Par parksto dans le forum Langage
    Réponses: 7
    Dernier message: 09/05/2004, 21h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo