Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 04/07/2013, à 08:36

Shanx

Python : écoute d’un port TCP

Bonjour à tous
je voudrais faire un programme en python qui joue un rôle de serveur : il écoute un port TCP (dans mes exemples le port 81), et quand il reçois quelque chose il répond sur le port 234. J’ai récupéré des morceaux de codes sur internet, et j’arrive à faire communiquer 2 programmes qui sont lancés sur la même machine. Par contre, impossible de faire ça entre deux stations différentes situées dans le même réseau local. hmm

Le serveur a pour adresse 192.168.0.70, et l’ordi avec lequel j’essaie de communiquer 192.168.0.54 (mais normalement on ne se sert pas de cette adresse IP). Le code serveur.py est le suivant :

#!/usr/bin/python3
#coding: utf-8
import socket
import time
Connecteur = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

Hote = '192.168.0.70' #IP du serveur
Port = 81
Connecteur.bind((Hote,Port))
print ("Le programme est a l'ecoute d'une eventuelle discussion, vous en serez averti.")
Connecteur.listen(2)
client, adresse = Connecteur.accept()
print ("L'ordinateur",adresse,"veut discuter ! J'attends son message.")

# Creation du connecteur de reponse
Reponse = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print("test1")
Portreponse = 234
print("test2")
time.sleep(2) # Temporisation necessaire, sinon echec même en local
Reponse.connect((Hote,Portreponse))
print ("Note : je me suis connecte a",adresse,"pour lui repondre")

while 1:
        Message = str(client.recv(255),'mac_roman')
        if not Message:
                break
        print ("\nMessage : ",Message,"\a" + "\n\nVotre reponse :")
        msgR = bytes(input('>> '), 'mac_roman')
        Reponse.send(msgR)        # envoi. 

client.close()

Et client.py :

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import socket
import time
Discuter = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
Hote = '192.168.0.70'
Port = 81
Port_de_reponse = 234
Discuter.connect((Hote,Port))
print("test1")
Reponse = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print("test2")

Reponse.bind((Hote,Port_de_reponse))
Reponse.listen(1)
print("test3")
client, adresse = Reponse.accept() 
print ("L'adresse",adresse," vous a entendu et attend votre message.")
while 1:
        msg = bytes(input('>> '), 'mac_roman')
        Discuter.send(msg) 
        print ("Attente de la reponse...")
        reponseaumessage = str(client.recv(255),'mac_roman')
        if not reponseaumessage:
                break  
        print ("\n",adresse,":",reponseaumessage,"\a\n")
 
client.close()

Et les erreurs que j’ai sont les suivantes :
sur le serveur :

$ sudo ./serveur.py 
Le programme est a l'ecoute d'une eventuelle discussion, vous en serez averti.
L'ordinateur ('192.168.0.54', 57185) veut discuter ! J'attends son message.
test1
test2
Traceback (most recent call last):
  File "./ecoute.py", line 21, in <module>
    Reponse.connect((Hote,Portreponse))
socket.error: [Errno 111] Connection refused

sur le client :

$ sudo client.py
test1
test2
Traceback (most recent call last):
  File "python/discussion.py", line 14, in <module>
    Reponse.bind((Hote,Port_de_reponse))
OSError: [Errno 99] Cannot assign requested address

Le message d’erreur apparait d’abord sur le client, mais je ne sais pas si c’est parce que c’est lui qui plante ou si c’est à cause de la temporisation sur le serveur.

J’ai pensé que les ports n’étaient pas ouverts, donc j’ai fait mumuse avec iptables et j’ai mis les même règles sur les deux machines :

$ sudo iptables -L                                           
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:234
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:81

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:234
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:81

Mais ça n’a rien changé. J’avoue que je commence à être perdu… Quelqu’un a une suggestion ?


Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied

Hors ligne

#2 Le 04/07/2013, à 09:11

grim7reaper

Re : Python : écoute d’un port TCP

Chezmoiçamarche.
Du moins quand je lance les deux en root (au passage, je trouve que c’est une mauvaise idée de passer par des ports réservés).
Par contre j’ai testé en local (127.0.0.70).
Bon du coup, à priori le problème ne devrait pas venir du code en lui-même.

sudo ./server.py
Le programme est a l'ecoute d'une eventuelle discussion, vous en serez averti.
L'ordinateur ('127.0.0.1', 36293) veut discuter ! J'attends son message.
test1
test2
Note : je me suis connecte a ('127.0.0.1', 36293) pour lui repondre

Message :  toto 

Votre reponse :
>> titi

Message :  foo 

Votre reponse :
>> bar
sudo ./client.py
test1
test2
test3
L'adresse ('127.0.0.1', 32960)  vous a entendu et attend votre message.
>> toto
Attente de la reponse...

 ('127.0.0.1', 32960) : titi 

>> foo
Attente de la reponse...

 ('127.0.0.1', 32960) : bar 

>> 

Sinon, ton sleep me semble inutile (du moins en local il ne sert à rien, ça fonctionne très bien sans)

Dernière modification par grim7reaper (Le 04/07/2013, à 09:15)

Hors ligne

#3 Le 04/07/2013, à 09:41

Jules Petibidon

Re : Python : écoute d’un port TCP

+1 quant aux ports connus.

Sinon ça sert à quoi d'utiliser des ports différents pour la requête et la réponse ?

Hors ligne

#4 Le 04/07/2013, à 09:56

Shanx

Re : Python : écoute d’un port TCP

@grim : oui, ça marche en local, c’est ce que j’avais dit :

j’arrive à faire communiquer 2 programmes qui sont lancés sur la même machine. Par contre, impossible de faire ça entre deux stations différentes situées dans le même réseau local. hmm

Du coup on est d’accord que le problème se trouve plutôt sur le réseau…

Le sleep est nécessaire, parce que le serveur est un raspberry (donc peu puissant), et si je ne le met pas le programme plante (je pense qu’il n’a pas le temps d’ouvrir un port ou une histoire du genre).

Je ne vois pas pourquoi c’est une mauvaise idée de passer par des ports réservés… D’ailleurs, je ne vois pas comment on peut faire sans ça. hmm

@Jules : j’ai essayé de mettre les mêmes ports, ça ne fonctionne pas. Je vais d’abord essayer de faire communiquer les deux stations, et une fois que ce era fait je verrais s’il y a des trucs à améliorer. wink


Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied

Hors ligne

#5 Le 04/07/2013, à 10:08

grim7reaper

Re : Python : écoute d’un port TCP

Shanx a écrit :

Du coup on est d’accord que le problème se trouve plutôt sur le réseau…

Pas sûr, mais en tout cas c’est le bind qui foire (et comme le bind foire, ensuite le connect du serveur foire aussi)

Shanx a écrit :

Le sleep est nécessaire, parce que le serveur est un raspberry (donc peu puissant), et si je ne le met pas le programme plante (je pense qu’il n’a pas le temps d’ouvrir un port ou une histoire du genre).

Ok, mais dans ce cas ton commentaire est faux (enfin, imprécis au point où il en devient factuellement faux).

Shanx a écrit :

Je ne vois pas pourquoi c’est une mauvaise idée de passer par des ports réservés… D’ailleurs, je ne vois pas comment on peut faire sans ça. hmm

Et bien parce qu’il sont réservé, c’est pas pour les appli’ de chez mémé.
Et c’est très facile de faire sans : il suffit de prendre un port > 1023 (seul les 1024 premiers sont réservés). En plus, tu n’auras plus besoin de lancer tes programmes en root comme ça.

Édit : d’ailleurs au passage, le bind dans ton client me chiffone. Un client est pas censé faire de bind

Dernière modification par grim7reaper (Le 04/07/2013, à 10:20)

Hors ligne

#6 Le 04/07/2013, à 10:19

Shanx

Re : Python : écoute d’un port TCP

Ah oui, c’est ça les ports réservés… En effet, j’avais prévu de prendre d’autres ports pour la suite. C’est juste que comme ça ne fonctionnait pas, j’ai tenté avec des ports moins exotiques (quand on est désespéré…).

Bon, du coup le bind ne fonctionne pas. Quelqu’un a une proposition de solution ?


Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied

Hors ligne

#7 Le 04/07/2013, à 10:31

grim7reaper

Re : Python : écoute d’un port TCP

Ouais, le bind client est bel et bien inutile.
Essaye ça :
* serveur

#!/usr/bin/python3
#coding: utf-8
import socket
import time

HOTE = '127.0.0.70' #IP du serveur
PORT = 8100

serv_soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
serv_soc.bind((HOTE, PORT))
serv_soc.listen(2)
print ("Le programme est a l'ecoute d'une eventuelle discussion, vous en serez averti.")

clt_soc, address = serv_soc.accept()
print ("L'ordinateur", address, "veut discuter ! J'attends son message.")

while 1:
    msg = str(clt_soc.recv(255),'mac_roman')
    if not msg:
        break
    print ('\nMessage : ', msg ,'\a' + '\n\nVotre reponse :')
    msgR = bytes(input('>> '), 'mac_roman')
    clt_soc.send(msgR)

clt_soc.close()
serv_soc.close()

* client

#!/usr/bin/python3
#coding: utf-8
import socket
import time

HOTE = '127.0.0.70'
PORT = 8100

soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.connect((HOTE, PORT))

while 1:
    msg = bytes(input('>> '), 'mac_roman')
    soc.send(msg)
    response = str(soc.recv(255),'mac_roman')
    if not response:
        break
    print ('\n','response:',response,'\a\n')

soc.close()

Va peut-être falloir que tu mettes ton sleep par contre.
Et puis changer les IP.

Dernière modification par grim7reaper (Le 04/07/2013, à 10:37)

Hors ligne

#8 Le 04/07/2013, à 10:44

Shanx

Re : Python : écoute d’un port TCP

serveur.py :

#!/usr /bin/python3
#coding: utf-8

import socket
import time

HOTE = '127.0.0.1' #IP du serveur
PORT = 8100

serv_soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
serv_soc.bind((HOTE, PORT))
serv_soc.listen(2)
print ("Le programme est a l'ecoute d'une eventuelle discussion, vous en serez averti.")

clt_soc, address = serv_soc.accept()
print ("L'ordinateur", address, "veut discuter ! J'attends son message.")

while 1:
    msg = str(clt_soc.recv(255),'mac_roman')
    if not msg:
        break
    print ("\nMessage : ", msg ,"\a" + "\n\nVotre reponse :")
    msgR = bytes(input('>> '), 'mac_roman')
    clt_soc.send(msgR)

clt_soc.close()
serv_soc.close()

client.py :

#!/usr/bin/python3
#coding: utf-8
import socket
import time

HOTE = '192.168.0.70'
PORT = 8100

soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.connect((HOTE, PORT))

while 1:
    msg = bytes(input('>> '), 'mac_roman')
    soc.send(msg)
    response = str(soc.recv(255),'mac_roman')
    if not response:
        break
    print ("\n",adresse,":",response,"\a\n")

soc.close()

Le serveur se lance bien, mais pas le client :

$ ./client.py  
Traceback (most recent call last):
  File "./client.py", line 10, in <module>
    soc.connect((HOTE, PORT))
ConnectionRefusedError: [Errno 111] Connection refused

Le serveur est lui imperturbable, il ne semble rien recevoir.
Pourtant j’ai bien rajouté une entrée dans iptables pour autoriser le trafic entrant sur le port 8100 sur le serveur.


Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied

Hors ligne

#9 Le 04/07/2013, à 10:51

tiramiseb

Re : Python : écoute d’un port TCP

Salut,

Je te propose de commencer par voir si c'est lié à ton programme ou au réseau (ou à autre chose, qui sait).
Au plus simple, je te dirais d'utiliser nc :

1/ sur le serveur :

nc -l -p 8100

2/ sur le client :

nc 192.168.0.70 8100

3/ sur le client, taper n'importe quoi :

toto

puis entrée, la chaîne devrait apparaître sur le serveur :

toto

Si à l'étape 2 ça déconne (ou éventuellement à la 3), alors c'est probablement un problème de réseau et tu peux faire tes tests avec nc de cette manière jusqu'à ce que ça marche. Ensuite tu retourneras sur ton programme en Python.

Hors ligne

#10 Le 04/07/2013, à 10:55

Shanx

Re : Python : écoute d’un port TCP

J’aurais du penser à faire ça. roll
Ça fonctionne parfaitement. Du coup, ça vient bien du programme. Je ne sais pas si c’est une bonne nouvelle ou pas. hmm


Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied

Hors ligne

#11 Le 04/07/2013, à 10:55

tiramiseb

Re : Python : écoute d’un port TCP

Par ailleurs, côté serveur je te conseille d'utiliser le module socketserver, plus haut niveau que socket...
http://docs.python.org/3/library/socket … er-example
(peut-être que ça résoudrait ton problème avec le "sleep" aussi... Mais je ne peux pas être affirmatif, je n'ai que survolé ton code)

Hors ligne

#12 Le 04/07/2013, à 10:58

tiramiseb

Re : Python : écoute d’un port TCP

« quand il reçois quelque chose il répond sur le port 234 » : je ne comprends pas ce que tu veux faire.
tu veux que, quand le serveur reçoit une requête, il initie une connexion vers le port 234 (ou autre) du client ?
Dans ce cas, ton client serait aussi un serveur...

Hors ligne

#13 Le 04/07/2013, à 11:18

Jules Petibidon

Re : Python : écoute d’un port TCP

A priori dans serveur.py :

HOTE = '127.0.0.1' #IP du serveur

Fait que le serveur ne répond qu'à lui même et refuse le reste

donc

HOTE = '192.168.0.70' #IP publique du serveur

ou encore

HOTE = '' #Répond à n'importe quoi d'après la doc

Hors ligne

#14 Le 04/07/2013, à 11:22

tiramiseb

Re : Python : écoute d’un port TCP

C't'œil de lynx Jules ! smile

Très bien vu, pour le code en #8.

Bon par contre le code en #1 a bien "Hote" en "192.168.0.70"...

Dernière modification par tiramiseb (Le 04/07/2013, à 11:22)

Hors ligne

#15 Le 04/07/2013, à 11:31

Shanx

Re : Python : écoute d’un port TCP

Bravo Jules smile
J’ai mis HOTE = '', et ça fonctionne (modulo une petite correction du code de grim). Maintenant le serveur écoute, et peut même répondre au client. smile

À terme, le client enverra des données au serveur, qui les stockera dans une bdd et enverra un acquittement. Vous venez de me tirer une sacrée épine du pied. smile


Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied

Hors ligne

#16 Le 04/07/2013, à 11:31

tiramiseb

Re : Python : écoute d’un port TCP

Sinon, sérieusement, utilise socketserver, ça va te simplifier la vie...

Hors ligne

#17 Le 04/07/2013, à 11:33

Shanx

Re : Python : écoute d’un port TCP

Ça va m’apporter quoi ?


Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied

Hors ligne

#18 Le 04/07/2013, à 11:41

tiramiseb

Re : Python : écoute d’un port TCP

Bah y'a rien qu'à voir l'exemple de code, c'est vachement plus simple. En plus c'est orienté objet.
Et puis ton code actuel, peut-il accepter des connexions de plusieurs clients ? J'ai l'impression qu'il est bloquant sur un seul client (mais je peux me tromper, je n'ai pas essayé).

Ton serveur en #8 devient :

#!/usr/bin/env python3
#coding: utf-8

HOTE = ''
PORT = 8100

import socketserver

class MonHandlerTCP(socketserver.BaseRequestHandler):
    def handle(self):
        print ("\nMessage : {}\a\n\nVotre reponse :".format(str(self.request.recv(1024).strip(), 'mac_roman')))
        self.request.sendall(bytes(input('>> '), 'mac_roman'))

if __name__ == "__main__":
    socketserver.TCPServer((HOTE, PORT), MonHandlerTCP).serve_forever()

Dernière modification par tiramiseb (Le 04/07/2013, à 11:43)

Hors ligne

#19 Le 04/07/2013, à 11:45

tiramiseb

Re : Python : écoute d’un port TCP

Par ailleurs, pourquoi "mac_roman" ? Tu ne fais pas tout en utf-8 ?
Moi mon terminal il est full UTF-8 en tout cas.

Hors ligne