异步服务器Python未调用handle_accept或其他处理方法

0 投票
1 回答
674 浏览
提问于 2025-04-17 11:53

我一直在尝试搭建一个简单的服务器,这样我和我的朋友就可以一起玩像“抓鱼”这样的简单卡牌游戏。我刚开始学习如何使用asyncore这个类,但遇到了一些问题。程序在没有服务器的情况下无法连接,但当服务器开启时,它显示连接成功,然而却从来没有调用handle_accept这个方法。如果我把handle_accept这个方法去掉,程序仍然可以连接,或者至少不会出现错误。
我一直在参考这个网站和关于Python asyncore方法的描述,但我不明白自己哪里出错了。
http://parijatmishra.wordpress.com/2008/01/04/writing-a-server-with-pythons-asyncore-module/

我已经包含了服务器和客户端的代码,以及两个用户界面的代码。

服务器用户界面

from Tkinter import *
from Server import *
import asyncore

class UI:

    # initialize UI
    def __init__(self, master):

        # create frame1
        frame1 = Frame(master, width=200, height=50)
        frame1.pack()

        # create frame2
        frame2 = Frame(master, width=200, height=50)
        frame2.pack()

        # create start button
        self.start = Button(frame1, text='Start Server', command=lambda: self.start_server())
        self.start.pack()

        # create end button
        self.stop = Button(frame1, text='Stop Server', command=lambda: self.stop_server())
        self.stop.pack()

        # create label
        self.label = Label(frame2)
        self.label.pack()

        # keep set size
        frame1.pack_propagate(0)
        frame2.pack_propagate(0)

    def start_server(self):

        try:
            self.server = Server()
            asyncore.loop()
        except:
            self.label.config(text='Error. A server is already running.')
        else:
            self.label.config(text='Server successfully started')

    def stop_server(self):

        try:
            self.server.stop() 
        except:
            self.label.config(text='Error. No server is running.')
        else:
            self.label.config(text='Server successfully stopped.')    

root = Tk()
ui = UI(root)
root.mainloop()

客户端用户界面

from Tkinter import *
from Client import *
import asyncore

class UI:

    # initialize the UI
    def __init__(self, master):

        # create frame1
        frame1 = Frame(master)
        frame1.pack()

        # create frame2
        frame2 = Frame(master, width=200, height=50)
        frame2.pack()

        # create frame3
        frame3 = Frame(master, width=200, height=50)
        frame3.pack()

        # create connect button
        self.connect = Button(frame1, text='Connect', command=lambda: self.connect_to_server())
        self.connect.pack(side=RIGHT)

        # create disconnect button
        self.disconnect = Button(frame1, text='Disconnect', command=lambda: self.disconnect_from_server())
        self.disconnect.pack()

        # create label
        self.label = Label(frame2, text='Enter host\'s ip')
        self.label.pack()

        # create entry box
        self.entry = Entry(frame3)
        self.entry.pack()

        # keep set size
        frame2.pack_propagate(0)
        frame3.pack_propagate(0)

    # connect to a server    
    def connect_to_server(self):

        ip = self.entry.get()

        try:
            self.client = Client(ip)
            asyncore.loop()
        except:
            self.label.config(text='Error. Unable to connect.')
        else:
            self.label.config(text='Successfully connected.')

    # disconnect from a server    
    def disconnect_from_server(self):
        try:
            self.client.disconnect()
        except:
            self.label.config(text='Error. Not connected to anything.')
        else:
            self.label.config(text='Successfully disconnected.')


root = Tk()
ui = UI(root)
root.mainloop()

服务器类

from socket import *
import asyncore

class Server(asyncore.dispatcher):

    # initialize a server
    def __init__(self):

        asyncore.dispatcher.__init__(self)
        self.host = '127.0.0.1'
        self.port = 50000 
        self.size = 1024
        self.s = socket(AF_INET, SOCK_STREAM)
        self.s.bind((self.host,self.port)) 
        self.s.listen(5)


    def stop(self):

        self.s.close()

    def readable(self):
        return True

    def handle_accept(self):
        client, addr = self.s.accept()
        print 'Incoming connection from ', repr(addr) 

客户端类

from socket import *
import asyncore

class Client(asyncore.dispatcher):

    def __init__(self, ip):

        asyncore.dispatcher.__init__(self)
        self.address = ip
        self.port = 50000 
        self.size = 1024
        self.s = socket(AF_INET, SOCK_STREAM)  
        self.s.connect((self.address, self.port)) 

    def disconnect(self):

        self.s.close()

    def send_data(self, msg):

        self.s.send(msg)

    def handle_connect(self):
        print 'Trying to connect'

1 个回答

1

handle_connect这个函数会在连接尝试成功或失败时都被调用。它的作用是告诉你连接尝试已经完成,并不是说一定成功了。你需要自己去检查一下,看看连接是否真的成功。

与其费劲去搞懂asyncore的各种复杂之处,不如直接使用Twisted。Twisted是一个活跃维护的库,文档也更完善,功能更多,而且能帮你屏蔽掉很多不必要的底层网络细节,让你专注于更重要的事情。

想要入门,可以看看这两个链接:服务器客户端的使用指南。

撰写回答