我在python中编写了一个简单的程序,使用asyncore和threading。我想实现一个异步客户端而不阻塞任何东西,比如:
How to handle asyncore within a class in python, without blocking anything?
这是我的代码:
import socket, threading, time, asyncore
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))
mysocket = Client("",8888)
onethread = threading.Thread(target=asyncore.loop)
onethread.start()
# time.sleep(5)
mysocket.send("asfas\n")
input("End")
现在异常将被发送到send(" asfas \ n"),因为我没有打开任何服务器。
我认为send函数中的异常将调用handle_error函数并且不会影响主程序,但大多数时候它会崩溃整个程序,有时它会起作用!如果我取消注释time.sleep(5),它只会使线程崩溃。为什么它会像这样?我可以编写一个不会使整个程序崩溃并且不使用time.sleep()的程序吗?谢谢! 错误讯息:
Traceback (most recent call last):
File "thread.py", line 13, in <module>
mysocket.send("asfas\n")
File "/usr/lib/python2.7/asyncore.py", line 374, in send
result = self.socket.send(data)
socket.error: [Errno 111] Connection refused
答案 0 :(得分:1)
首先,我建议不要使用旧的asyncore模块,而是要考虑更多 现代和更有效的解决方案:gevent,或者沿着asyncio模块(Python 3.4), 已经以某种方式向Python 2反向移植。
如果你想使用asyncore,那么你必须知道:
使用在一个线程(主线程,在你的情况下)中创建的套接字并由另一个线程调度(在你的情况下由“onethread”管理)时要小心,线程之间不能像这样共享套接字它本身不是线程安全的对象
出于同样的原因,您无法使用asyncore模块中默认创建的全局地图,您必须按线程创建地图
连接到服务器时,连接可能不是立即连接,您必须等待它连接(因此您的“睡眠5”)。使用asyncore时,会调用“handle_write” socket已准备好发送数据。
以下是您的代码的较新版本,希望它能解决这些问题:
import socket, threading, time, asyncore
class Client(threading.Thread, asyncore.dispatcher):
def __init__(self, host, port):
threading.Thread.__init__(self)
self.daemon = True
self._thread_sockets = dict()
asyncore.dispatcher.__init__(self, map=self._thread_sockets)
self.host = host
self.port = port
self.output_buffer = []
self.start()
def run(self):
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((self.host, self.port))
asyncore.loop(map=self._thread_sockets)
def send(self, data):
self.output_buffer.append(data)
def handle_write(self):
all_data = "".join(self.output_buffer)
bytes_sent = self.socket.send(all_data)
remaining_data = all_data[bytes_sent:]
self.output_buffer = [remaining_data]
mysocket = Client("",8888)
mysocket.send("asfas\n")
如果你的线程只有1个套接字(即调度程序的大小为1的地图),则没有 完全使用asyncore。只需在线程中使用普通的阻塞套接字即可。该 async i / o的好处是有很多套接字。
编辑:答案已在评论后进行了编辑。