OVH Cloud OVH Cloud

Serveur et paquets

8 réponses
Avatar
Yves Lange
Bonjour,
j'ai crée un petit script python qui, en socket TCP/IP, écoute sur un
port: une serveur ^^. Le serveur reçoit une masse d'informations
(environ 5000 paquet de 1024, donc un buffer de 1024).
J'ai alors deux problème. Le premier est que le serveur bloque à chaque
fois à environ 3900 paquet pendant environ 15 à 30 secondes ce qui est
gênant puisque il faut attendre à que la transmission de donnée reprenne.
Le deuxième problème c'est que mon script ressemble à ça:
while 1:
s = socket(...)
s.connect(...)
s.send(...)
s.recv(1024)
s.close(...)

N'y aurait-il pas un moyen de le faire ressembler à un vrai dialogue
TCP/IP, donc éviter de réinisialiser à chaque fois la connection et d'en
créer une nouvelle, exemple:
s=socket(...)
s.connect(...)
while 1:
s.send(...)
s.recv(1024)
s.close(...)


Et du coté serveur, ça serait ?
s=socket(...)
s.bind(...)
s.listen(...)
while 1:
s.recv(1024)
s.send(...)
s.close(...)

J'attends vos réponses avec impatience, merci ^^

8 réponses

Avatar
Yves Lange
Bonjour,
j'ai crée un petit script python qui, en socket TCP/IP, écoute sur un
port: une serveur ^^. Le serveur reçoit une masse d'informations
(environ 5000 paquet de 1024, donc un buffer de 1024).
J'ai alors deux problème. Le premier est que le serveur bloque à chaque
fois à environ 3900 paquet pendant environ 15 à 30 secondes ce qui est
gênant puisque il faut attendre à que la transmission de donnée reprenne.
Le deuxième problème c'est que mon script ressemble à ça:
while 1:
s = socket(...)
s.connect(...)
s.send(...)
s.recv(1024)
s.close(...)

N'y aurait-il pas un moyen de le faire ressembler à un vrai dialogue
TCP/IP, donc éviter de réinisialiser à chaque fois la connection et d'en
créer une nouvelle, exemple:
s=socket(...)
s.connect(...)
while 1:
s.send(...)
s.recv(1024)
s.close(...)


Et du coté serveur, ça serait ?
s=socket(...)
s.bind(...)
s.listen(...)
while 1:
s.recv(1024)
s.send(...)
s.close(...)

J'attends vos réponses avec impatience, merci ^^
Mes recherches mon amené à Twisted mais comment l'utiliser ???


Avatar
DarkPearl
Bonjour à vous, je vous donne vite fait une réponse en ce lundi matin
à 6h45.... dur dur.

Alors effectivement, ton serveur n'est pas au point. C'est pas tres
propre.
Quand tu recois plusieurs paquets, tu n'est pas obligé de recréer une
socket à chaque fois. Tu dois donc sortir le sock=socket(...) de ta
boucle while. Ensuite il faut aussi que tu sorte le sock.close().

Enfin, l'avantage avec tcp, c'est que tu es sûr que les données
arrivent mais ca ne veut pas dire que tu vas recevoir à cout sur des
paquets de 1024. Il faut donc que tu créé une fonction rcvAll qui
fera comme sendall. Cependant, il n'y a pas de recette miracle pour ce
rcvAll.

Je te donne vite fait un exemple de socket de reception en TCP que
j'utilise pour un de mes gros serveurs...

try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print "Impossible de creer la socket serveur"
exit(1)
try:
sock.bind(('',PORT_SOCKET_RECEPTION))
except:
print "impossible d'ouvrir la socket de reception"
exit(1)
try:
sock.listen(LISTEN_SOCKET_RECEPTION)
except:
print "l'attribut listen de la socket n'a pas pu etre modifier"

timeSock = timeoutsocket.TimeoutSocket(sock,serveur.periodeTimeOut)

while True:
try:
receptionSocket, adresse = timeSock.accept()

except timeoutsocket.Timeout:
print "Timeout"
continue




res =""
receptionSocket.set_timeout(1)

while True:

try:
rcv = receptionSocket.recv(TAILLE_BUFFER_RECEPTION)
except timeoutsocket.Timeout:
break

res = res+rcv
if len(rcv)==0:break



Tu trouvera ton message total dans "res".
Il te faut aussi telecharger la classe Timeoutsocket à cette adresse
"www.timo-tasi.org/python/timeoutsocket.py"

J'ai mis la notion de timeout afin d'etre quasiment sur de recevoir la
totalité du message.
La première socket avec le timeout me permet de me debloquer pour
faire des actions spécifiques


bonne continuation
mais tu n'es pas obligé de l'utiliser.
Avatar
hg
Yves Lange wrote:

Bonjour à vous, je vous donne vite fait une réponse en ce lundi matin
à 6h45.... dur dur.

Alors effectivement, ton serveur n'est pas au point. C'est pas tres
propre.
Quand tu recois plusieurs paquets, tu n'est pas obligé de recréer une
socket à chaque fois. Tu dois donc sortir le sock=socket(...) de ta
boucle while. Ensuite il faut aussi que tu sorte le sock.close().

Enfin, l'avantage avec tcp, c'est que tu es sûr que les données
arrivent mais ca ne veut pas dire que tu vas recevoir à cout sur des
paquets de 1024. Il faut donc que tu créé une fonction rcvAll qui
fera comme sendall. Cependant, il n'y a pas de recette miracle pour ce
rcvAll.

Je te donne vite fait un exemple de socket de reception en TCP que
j'utilise pour un de mes gros serveurs...

try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print "Impossible de creer la socket serveur"
exit(1)
try:
sock.bind(('',PORT_SOCKET_RECEPTION))
except:
print "impossible d'ouvrir la socket de reception"
exit(1)
try:
sock.listen(LISTEN_SOCKET_RECEPTION)
except:
print "l'attribut listen de la socket n'a pas pu etre modifier"

timeSock = timeoutsocket.TimeoutSocket(sock,serveur.periodeTimeOut)

while True:
try:
receptionSocket, adresse = timeSock.accept()

except timeoutsocket.Timeout:
print "Timeout"
continue




res =""
receptionSocket.set_timeout(1)

while True:

try:
rcv = receptionSocket.recv(TAILLE_BUFFER_RECEPTION)
except timeoutsocket.Timeout:
break

res = res+rcv
if len(rcv)==0:break



Tu trouvera ton message total dans "res".
Il te faut aussi telecharger la classe Timeoutsocket à cette adresse
"www.timo-tasi.org/python/timeoutsocket.py"

J'ai mis la notion de timeout afin d'etre quasiment sur de recevoir la
totalité du message.
La première socket avec le timeout me permet de me debloquer pour
faire des actions spécifiques


bonne continuation
mais tu n'es pas obligé de l'utiliser.

Yeah...


Merci beaucoup pour votre réponse très spécifique à mon problème ^^
Donc pas besoin de récréer à chaque fois une socket et de le fermer mais
bon j'ai pour projet de simultanément plusieurs utilisateur c'est pour
cette raison que j'ouvre et que je referme en boucle...

Avez-vous d'autre idée ?

++
merci encore


Il faut créer un serveur de sockets.

Pour ce faire, tu dois avoir une application qui dérive de threading.Thread.

Ta tache principale fait son initialisation, puis "bind" puis "listen"(appel
bloquant) ... dès qu'un client fait un "connect", la tache se réveille avec
un nouveau socket, lié au client ... tu lance un thread avec cette socket
en paramètre puis te remets en attente sur listen pour un autre client.


Attention de bien utiliser "join" en fin de programme pour assurer que tous
les thread se terminent bien.

hg


Avatar
Yves Lange
Bonjour à vous, je vous donne vite fait une réponse en ce lundi matin
à 6h45.... dur dur.

Alors effectivement, ton serveur n'est pas au point. C'est pas tres
propre.
Quand tu recois plusieurs paquets, tu n'est pas obligé de recréer une
socket à chaque fois. Tu dois donc sortir le sock=socket(...) de ta
boucle while. Ensuite il faut aussi que tu sorte le sock.close().

Enfin, l'avantage avec tcp, c'est que tu es sûr que les données
arrivent mais ca ne veut pas dire que tu vas recevoir à cout sur des
paquets de 1024. Il faut donc que tu créé une fonction rcvAll qui
fera comme sendall. Cependant, il n'y a pas de recette miracle pour ce
rcvAll.

Je te donne vite fait un exemple de socket de reception en TCP que
j'utilise pour un de mes gros serveurs...

try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print "Impossible de creer la socket serveur"
exit(1)
try:
sock.bind(('',PORT_SOCKET_RECEPTION))
except:
print "impossible d'ouvrir la socket de reception"
exit(1)
try:
sock.listen(LISTEN_SOCKET_RECEPTION)
except:
print "l'attribut listen de la socket n'a pas pu etre modifier"

timeSock = timeoutsocket.TimeoutSocket(sock,serveur.periodeTimeOut)

while True:
try:
receptionSocket, adresse = timeSock.accept()

except timeoutsocket.Timeout:
print "Timeout"
continue




res =""
receptionSocket.set_timeout(1)

while True:

try:
rcv = receptionSocket.recv(TAILLE_BUFFER_RECEPTION)
except timeoutsocket.Timeout:
break

res = res+rcv
if len(rcv)==0:break



Tu trouvera ton message total dans "res".
Il te faut aussi telecharger la classe Timeoutsocket à cette adresse
"www.timo-tasi.org/python/timeoutsocket.py"

J'ai mis la notion de timeout afin d'etre quasiment sur de recevoir la
totalité du message.
La première socket avec le timeout me permet de me debloquer pour
faire des actions spécifiques


bonne continuation
mais tu n'es pas obligé de l'utiliser.

Yeah...


Merci beaucoup pour votre réponse très spécifique à mon problème ^^
Donc pas besoin de récréer à chaque fois une socket et de le fermer mais
bon j'ai pour projet de simultanément plusieurs utilisateur c'est pour
cette raison que j'ouvre et que je referme en boucle...

Avez-vous d'autre idée ?

++
merci encore

Avatar
Amaury Forgeot d'Arc

Il faut créer un serveur de sockets.

Pour ce faire, tu dois avoir une application qui dérive de threading.Thread.

Ta tache principale fait son initialisation, puis "bind" puis "listen"(appel
bloquant) ... dès qu'un client fait un "connect", la tache se réveille avec
un nouveau socket, lié au client ... tu lance un thread avec cette socket
en paramètre puis te remets en attente sur listen pour un autre client.


Pour cela il y a une classe toute faite:
ThreadingTCPServer dans le module SocketServer.
J'ai trouvé un exemple d'utilisation ici:
http://mail.python.org/pipermail/python-list/2005-July/330814.html
Et la doc de référence est là:
http://docs.python.org/lib/module-SocketServer.html

Il "suffit" de créer une classe qui dérive de BaseRequestHandler, et qui
implémente la méthode "handle".
Puis on démarre le serveur en deux lignes:
srv = ThreadingTCPServer(('', port), Broker)
srv.serve_forever()

ça, c'est quand le nombre de connections simultanées reste raisonnable :
au delà de 100 threads, il vaut mieux trouver autre chose. C'est là que
twisted pourra aider. Mais en attendant, SocketServer m'a rendu de bons
service!

--
Amaury Forgeot d'Arc

Avatar
hg
DarkPearl wrote:

Les 2 ont leurs avantages neanmoins il vaut mieux utiliser un serveur
iteratif sauf si le temps de réponse du serveurs aux requetes est long
(j'entend par long, qui doit faire des E/S et donc qui ralenti
enormement le traitement)


ben pas vraiment d'accord ... ça a tendance à rendre le code "brouillon"

Mais sache que c'est mieux de faire soit
meme la partie réseau de ton serveur..


Là d'accord

hg

Avatar
DarkPearl
Rebonjour à vous, je reviens dans la conversation pour ajouter des
précisions car ca n'a pas l'air clair pour vous.

Tout d'abord il est important de savoir se qu'on fait et pourquoi on le
fait .

Quand on veut faire un serveur, il faut tout d'abord savoir que l'on a
en gros 2 possibilités :
-> soit on fait un serveur iteratif (les requetes sont traitées les
unes apres les autres)
-> soit on fait un serveur concurrent (les requetes sont traitées en
parrallèles) (grace à des fork (linux) ou des threads (windob))

Les 2 ont leurs avantages neanmoins il vaut mieux utiliser un serveur
iteratif sauf si le temps de réponse du serveurs aux requetes est long
(j'entend par long, qui doit faire des E/S et donc qui ralenti
enormement le traitement)

De toute facon, ne t'inquiete pas, le "listen" te permet de definir une
file d'attente. Si le traitement des requetes au serveur est rapide
alors meme tes utilisateurs en simultané ne veront pas la difference.

Pour recapituler, si tu dois accéder à des ressources fichiers ou
réseau avec ton serveur pour répondre à des requetes, fabrique un
serveur concurrent sinon fait un serveur iteratif. Tu gagnera en
simplicité et en rapidité.


Mais ne t'inquiete pas, j'ai remarqué que tu tenais absolument à
utiliser twisted, donc va y. Mais sache que c'est mieux de faire soit
meme la partie réseau de ton serveur...


A plus
Avatar
Yves Lange
DarkPearl wrote:


Les 2 ont leurs avantages neanmoins il vaut mieux utiliser un serveur
iteratif sauf si le temps de réponse du serveurs aux requetes est long
(j'entend par long, qui doit faire des E/S et donc qui ralenti
enormement le traitement)



ben pas vraiment d'accord ... ça a tendance à rendre le code "brouillon"


Mais sache que c'est mieux de faire soit
meme la partie réseau de ton serveur..



Là d'accord

hg

Merci pour vos réponses, je fais une serveur itératif. C'est plus simple

à comprendre et à coder ^^