python中的asyncore.dispatcher:handle_closed和handle_read何时执行?

Sea*_*ene 3 python sockets asyncore

有两个文件:server.py和client.py,都是在asyncore.dispatcher的帮助下编写的

Server.py

import asyncore, socket

class Server(asyncore.dispatcher):
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind(('', port))
        self.listen(1)
        print "Waiting for connection..."

    def handle_accept(self):
        socket, address = self.accept()
        print 'Connection by', address
        socket.send("Hello Server")

    def handle_read(self):
        print "Reading..."
        out_buffer = self.recv(1024)
        if not out_buffer:
            self.close()
        print out_buffer

    def handle_closed(self):
        print "Server: Connection Closed"
        self.close()

s = Server('0.0.0.0', 5007)
asyncore.loop()
Run Code Online (Sandbox Code Playgroud)

Client.py

import asyncore, socket

class Client(asyncore.dispatcher):
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, port))
        print "Client Start..."

    def handle_close(self):
        print "Client: Connection Closed"
        self.close()

    def handle_read(self):
        data = self.recv(1024)
        if data:
            print "Received ", data
        self.send("Hello Client")

c = Client('127.0.0.1', 5007)
asyncore.loop()
Run Code Online (Sandbox Code Playgroud)

结果:

执行server.py:

Waiting for connection...
Run Code Online (Sandbox Code Playgroud)

然后client.py:

Client Start...
Received  Hello Server
Client: Connection Closed
Client: Connection Closed
Run Code Online (Sandbox Code Playgroud)

最后,client.py退出,在server.py的输出窗口中显示另一行,服务器继续运行:

Connection by ('127.0.0.1', 58197)
Run Code Online (Sandbox Code Playgroud)

有一些我无法理解的东西:

  1. 为什么功能handle_closed在client.py执行两次?

  2. 为什么不是函数handle_reading在server.py执行?该client.py已发送的消息("你好客户"),但为什么不能在服务器接受呢?

  3. 为什么不是函数handle_closed在server.py执行?我想在客户端退出时在server.py中执行一些代码,但似乎它handle_closed在server.py中无关紧要?

Dan*_*wka 9

Asyncore谈话

将handle_read()在server.py将永远不会被调用.

但为什么?!这是一个服务器类......

是的,但是Server类使用它的套接字来监听任何未建立的连接.对它的任何读取都会进入handle_accept(),其中实际的通道套接字(连接到某个端点)应该被赋予某个非dispatcher继承类的新实例(最好).在你Server的handle_accept()方法中,获取的套接字accept()是本地的,因此在退出此函数时被删除,因此:接受新连接,发送文本并在该套接字立即被杀死之后.

在其他问题上阅读asyncore模块和我的答案.

服务器

你需要像我说的那样为server.py中的连接创建新类:

class ClientHandler(asyncore.dispatcher):
    def handle_read(self):
        data = self.recv(1024)
        if not data:
            return
        print "Received:", data

    def handle_close(self):
        print "Server: Connection Closed"
        self.close()
Run Code Online (Sandbox Code Playgroud)

请注意,当收到null时,读取不需要手动关闭套接字 - asyncore负责正确关闭连接.

然后你必须在Server连接时实例化它:

    def handle_accept(self):
        ...
        ClientHandler(socket)
Run Code Online (Sandbox Code Playgroud)

你也拼错了Server- 方法的正确名称是handle_close.虽然它没用.与客户端连接相关的所有内容都在ClientHandler.

客户

在client.py中,您只需要修改handle_read():

    if data:
        print "Received ", data
Run Code Online (Sandbox Code Playgroud)

改成:

    if not data:
        return
    print "Received ", data
Run Code Online (Sandbox Code Playgroud)

为什么?如果没有这个send(),即使套接字实际上是关闭的,也会被调用,导致handle_close()被第二次调用asyncore.就像我说的那样 - asyncore照顾好这个.

笔记

现在,您可以为连接编写更复杂的服务器端类.您还可以了解操作系统级套接字的工作原理,这样您就不会遇到麻烦.

asyncore本身对于套接字来说是一个非常好的包装器,但如果你想在某些事件驱动的环境中做更高级的事情,比如HTTP或SMTP处理,那么Twisted库会让你感兴趣!