asyncore 未运行handle_read

发布于 2024-08-08 06:19:44 字数 1252 浏览 8 评论 0原文

我试图制作一个简单的异步示例,其中一个套接字是发送者,一个是接收者。由于某种原因,接收器上的handle_read()永远不会被调用,所以我永远不会得到“测试”数据。有人知道为什么吗?这是我第一次尝试 asyncore,所以它可能非常简单。

import asyncore, socket, pdb, random

class Sender(asyncore.dispatcher):
    def __init__(self):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)

    def handle_connect(self):
        print ('first connect')

    def writable(self):
        True

    def readable(self):
        return False

    def handle_write(self):
        pass

    def handle_close(self):
        self.close()

class Receiver(asyncore.dispatcher):
    def __init__(self):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)

    def handle_connect(self):
        print ('first connect')

    def readable(self):
        return True

    def handle_read(self):
        print 'reading'

    def handle_write(self):
        print 'write'

    def handle_accept(self):
        self.conn_sock, addr = self.accept()
        print 'accepted'

    def handle_close(self):
        self.close()
a = Sender()
b = Receiver()
addr = ('localhost', 12344)
b.bind(addr)
b.listen(1)
a.connect(addr)
asyncore.loop()
a.send('test')

I'm trying to just make a simple asyncore example where one socket is the sender and one is the receiver. For some reason, the handle_read() on the receiver is never called so I never get the 'test' data. Anyone know why? This is my first shot at asyncore, so it's probably something extremely simple.

import asyncore, socket, pdb, random

class Sender(asyncore.dispatcher):
    def __init__(self):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)

    def handle_connect(self):
        print ('first connect')

    def writable(self):
        True

    def readable(self):
        return False

    def handle_write(self):
        pass

    def handle_close(self):
        self.close()

class Receiver(asyncore.dispatcher):
    def __init__(self):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)

    def handle_connect(self):
        print ('first connect')

    def readable(self):
        return True

    def handle_read(self):
        print 'reading'

    def handle_write(self):
        print 'write'

    def handle_accept(self):
        self.conn_sock, addr = self.accept()
        print 'accepted'

    def handle_close(self):
        self.close()
a = Sender()
b = Receiver()
addr = ('localhost', 12344)
b.bind(addr)
b.listen(1)
a.connect(addr)
asyncore.loop()
a.send('test')

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

妳是的陽光 2024-08-15 06:19:44

asyncore.loop 不会终止,因此 a.send 不会发生,因为您已将其编码为在之后行中发生asyncore.loop 退出。

一旦解决了这个问题,您就会遇到在单个线程和进程中运行发送方和接收方的问题,因此除非您采取非常微妙的步骤来确保一切都按正确的顺序发生,否则您将陷入僵局。 asyncore 当然是为了在单独运行的进程之间使用,所以这个问题在正常的实际使用中不会出现。如果您对死锁的确切位置感到好奇,请制作自己的 asyncore 副本并在其中添加 print 语句,或者尝试

python -m trace -t ast.py

不幸的是,后者给出了很多输出并且不显示关键变量的值。因此,虽然尝试起来很轻松且非侵入性,但它的帮助远不如一些战略性放置的 print (例如,每次选择之前和之后的 r 和 w fd 列表)。

我相信(但没有深入调试它,因为无论如何这是一个不切实际的场景)选择仅触发一次(因为您同时接受/连接和向套接字写入字节的情况发生)在第一次选择之前,它们最终“折叠”成一个事件),但是该事件的处理无法知道折叠(正常使用中不会发生!-),因此它只处理接受/连接。但如果您花时间进行更深入的调试,您无疑会更好地理解这种异常情况!

asyncore.loop does not terminate, so the a.send doesn't happen, since you've coded it to happen in line after the exit of asyncore.loop.

Once this is fixed, you run into the problem that you're running sender and receiver within a single thread and process, so unless you take very delicate steps to ensure everything happens in the right order, you ARE going to get deadlocked. asyncore is of course meant to be used among processes running separately, so the problem just doesn't appear in normal, real-world uses. If you're curious about exactly where you're deadlocking, make your own copy of asyncore and pepper it with print statements, or, try

python -m trace -t ast.py

Unfortunately, the latter gives a lot of output and doesn't show crucial variables' values. so, while painless and non-invasive to try, it's far less helpful than a few strategically placed prints (e.g., the r and w fd lists just before and after each select).

I believe (but haven't debugged it in depth, since it's an unrealistic scenario anyway) that the select triggers only once (because you have both the accept/connect and the writing of bytes to the socket happen before the first select, they end up "collapsed" into a single event), but the handling of that one event can't know about the collapsing (wouldn't happen in normal use!-) so it only deals with the accept/connect. But if you take the time to debug in greater depth you may no doubt understand this anomalous scenario better!

倾`听者〃 2024-08-15 06:19:44

很晚了,没有解决问题,因为亚历克斯指出了原因,但你的代码显示:

def writable(self):
     True 

不应该是:

def writable(self):
     return True 

A lot late and not solving the issue as Alex points to the causes, but your code shows:

def writable(self):
     True 

Shouldn't that be:

def writable(self):
     return True 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文