Question

Le code suivant ne fonctionne pas correctement sous Windows (mais fonctionne sous Linux):

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setblocking(True)
    sock.connect(address)
    gobject.io_add_watch(
            sock.fileno(),
            gobject.IO_OUT | gobject.IO_ERR | gobject.IO_HUP,
            callback)

Des extraits de commentaires à différents endroits de la source Glib et d’autres endroits mentionnent que, dans Windows, les sockets sont mises en mode non bloquant lors de l’interrogation. Par conséquent, le rappel self.outgoing_cb est appelé en permanence et l'écriture dans le socket échoue avec le message d'erreur suivant:

[Errno 10035] A non-blocking socket operation could not be completed immediately

L'appel de sock.setblocking (True) avant l'écriture ne semble pas le contourner. En réduisant la priorité de l'interrogation et en ignorant le message d'erreur, cela fonctionne comme prévu, mais génère beaucoup d'événements et consomme beaucoup de temps processeur. Existe-t-il un moyen de contourner cette limitation dans Windows?

Mettre à jour

Je ferai remarquer que l'intérêt de POLLOUT est que lorsque vous passez l'appel en écriture, vous n'obtiendrez pas EAGAIN / EWOULDBLOCK . Le message d'erreur étrange que je reçois, je pense serait l'équivalent Windows de ces 2 codes d'erreur. En d'autres termes, je reçois des événements gobject.IO_OUT lorsque le socket ne me permet pas d'écrire avec succès. et , le fait de le bloquer en mode bloquant me donne toujours cette erreur inappropriée. / p>

Une autre mise à jour

Sous Linux, où cela fonctionne correctement, le socket n'est pas en mode non-bloquant et je reçois IO_OUT , lorsque le socket me permet d'écrire sans bloquer ni de générer une erreur. C’est cette fonctionnalité que je souhaite mieux émuler / restaurer sous Windows.

Notes complémentaires

À partir de man poll :

   poll()  performs a similar task to select(2): it waits for one of a set
   of file descriptors to become ready to perform I/O.
          POLLOUT
                 Writing now will not block.

Dans , sélectionnez :

A file descriptor  is considered ready if it is possible to perform the corre‐
sponding I/O operation (e.g., read(2)) without blocking.
Était-ce utile?

La solution

Existe-t-il un problème avec les E / S non bloquantes? Il semble étrange d'utiliser des boucles d'interrogation si vous utilisez le blocage d'E / S.

Quand j'écris des programmes comme celui-ci, j'ai tendance à faire ce qui suit:

  • Mettez en tampon les octets que je veux envoyer au descripteur de fichier.

  • Ne demandez que les événements IO_OUT (ou l'équivalent poll () , POLLOUT ) lorsque ledit tampon n'est pas vide.

  • Lorsque poll () (ou son équivalent) a signalé que vous êtes prêt à écrire, lancez l'écriture. Si vous obtenez EAGAIN / EWOULDBLOCK , supprimez les octets que vous avez écrits avec succès dans la mémoire tampon et attendez la prochaine fois que vous êtes signalé. Si vous avez réussi à écrire tout le tampon, arrêtez de demander POLLOUT afin de ne pas vous réveiller de manière fausse.

(J'imagine que les liaisons Win32 utilisent WSAEventSelect et WaitForMultipleObjects () pour simuler poll () , mais le résultat est le même ...)

Je ne suis pas sûr de savoir comment votre approche souhaitée avec des sockets à blocage fonctionnerait. Vous êtes "en train de vous réveiller" constamment parce que tu as demandé à te réveiller quand tu sais écrire. Vous voulez seulement spécifier que lorsque vous avez des données à écrire ... Mais ensuite, quand cela vous réveillera, le système ne vous dira pas vraiment combien de données vous pouvez écrire sans bloquer, c'est donc une bonne raison d'utiliser des E / S non bloquantes.

Autres conseils

GIO contient GSocket , un" objet de socket réseau de bas niveau " depuis 2.22. Toutefois, cela doit encore être porté sur le pygobject sous Windows .

Je ne suis pas sûr que cela aide (je ne maîtrise pas la fonction de sondage ni les prises MFC et je ne sais pas si le sondage est une exigence de la structure de votre programme), prenez donc ceci avec un grain de sel:

Mais pour éviter un blocage ou EAGAIN lors de l'écriture, nous utilisons select, c'est-à-dire, ajoutons le socket au jeu d'écriture passé à select, et si select () revient avec rc = 0, le socket acceptera immédiatement les écritures. ..

La boucle d'écriture utilisée dans notre application est (en pseudocode):

set_nonblocking.
count= 0.
do {
   FDSET writefds;
   add skt to writefds.
   call select with writefds and a reaonsable timeout.
   if (select fails with timeout) {
       die with some error;
   } 

   howmany= send(skt, buf+count, total-count).
   if (howmany>0) {
       count+= howmany.
   }
} while (howmany>0 && count<total);

Vous pouvez utiliser Twisted , qui inclut supporte GTK (même sous Windows) et gèrera tous les diverses conditions d'erreur que les sockets non bloquants sous Windows aiment lever.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top