Python asynchat 状态

0 投票
1 回答
812 浏览
提问于 2025-04-16 21:46

我刚开始学习Python的socket网络编程。为了更好地理解这个概念,我在尝试搭建一个简单的服务器,这个服务器会询问客户端想要的文件类型,然后在收到文件扩展名后,再询问具体的文件。我在网上找到了很多教程,主要是使用asyncore库,特别是asynchat来实现这种请求和响应的功能。

我跟着的一个最基本的教程可以在这里找到(我已经复制过来了)

http://effbot.org/librarybook/asynchat.htm

import asyncore, asynchat
import os, socket, string

PORT = 8000

class HTTPChannel(asynchat.async_chat):

    def __init__(self, server, sock, addr):
        asynchat.async_chat.__init__(self, sock)
        self.set_terminator("\r\n")
        self.request = None
        self.data = ""
        self.shutdown = 0

    def collect_incoming_data(self, data):
        self.data = self.data + data

    def found_terminator(self):
        if not self.request:
            # got the request line
            self.request = string.split(self.data, None, 2)
            if len(self.request) != 3:
                self.shutdown = 1
            else:
                self.push("HTTP/1.0 200 OK\r\n")
                self.push("Content-type: text/html\r\n")
                self.push("\r\n")
            self.data = self.data + "\r\n"
            self.set_terminator("\r\n\r\n") # look for end of headers
        else:
            # return payload.
            self.push("<html><body><pre>\r\n")
            self.push(self.data)
            self.push("</pre></body></html>\r\n")
            self.close_when_done()

class HTTPServer(asyncore.dispatcher):

    def __init__(self, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind(("", port))
        self.listen(5)

    def handle_accept(self):
        conn, addr = self.accept()
        HTTPChannel(self, conn, addr)

#
# try it out

s = HTTPServer(PORT)
print "serving at port", PORT, "..."

我想问的是关于HTTPServer类中的handle_accept方法。如果每次有请求进来时,HTTPChannel对象都会被初始化,那在这种情况下,创建请求和响应的机制岂不是不可能吗?我在想,是否可以在通道对象中设置一些标志,比如_hastype_hasfile,但是因为每个连接的accept都会初始化这个对象,所以每次请求时对象的状态都会被重置。我知道这个设置是为了创建一个基本的HTTPServer,但我想知道我该如何修改它,以实现我描述的功能?服务器对象是否需要直接继承asynchat,而完全放弃dispatcher?通道对象需要有一些状态来知道文件类型已经发送过,然后再请求文件的二进制数据。我非常好奇,这种实现方式最简洁的样子会是什么样的。

非常感谢——我对socket编程还很陌生。如果我说得不够清楚,请告诉我。

1 个回答

1

通常情况下,连接在最开始建立后会保持打开状态,这样来自同一个客户端的所有通信都会通过同一个 HTTPChannel 对象进行。只有在创建新连接时,才会调用 accept 方法。

撰写回答