在SMTPD组件的基础上,我使用授权等编写了自己的SMTP服务器......我需要做的最后一件事是在新线程到来时添加消息解析。
所以我的组件包含两个类:SMTPServer
和SMTPChannel
。它在这样的一个线程中完美地运行:
def handle_accept(self):
pair = self.accept()
if pair is not None:
conn, addr = pair
logging.info('Incoming connection from ' + str(addr))
channel = SMTPChannel(config, conn, addr)
日志看起来像这样:
kiril@kiril-X501A1 ~/www/py_email $ python SMTPServer.py
[2015-05-27 11:15:57] [MainThread] INFO: Server started at 192.168.0.103:1026
[2015-05-27 11:16:46] [MainThread] INFO: Incoming connection from ('192.168.0.46', 52423)
[2015-05-27 11:16:46] [MainThread] DEBUG: <-- '220 SMTP Server 0.1 ESMTP'
[2015-05-27 11:16:46] [MainThread] DEBUG: --> EHLO : '*******'
[2015-05-27 11:16:46] [MainThread] DEBUG: <-- '250-SMTP Server 0.1 ESMTP Hello *******\n250-SIZE 20480000\n250 AUTH PLAIN LOGIN CRAM-MD5'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> AUTH : 'PLAIN AGFkbWluADEyMzQ='
[2015-05-27 11:16:47] [MainThread] INFO: ('192.168.0.46', 52423) successfully authenticated
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '235 Authentication successful.'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> MAIL : 'FROM:<reply@*******>'
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> RCPT : 'TO:<destination@*******>'
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> DATA
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '354 End data with <CR><LF>.<CR><LF>'
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> QUIT
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '221 Bye'
[2015-05-27 11:16:47] [MainThread] INFO: Incoming connection from ('192.168.0.46', 52422)
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '220 SMTP Server 0.1 ESMTP'
[2015-05-27 11:16:47] [MainThread] DEBUG: --> EHLO : '*******'
[2015-05-27 11:16:47] [MainThread] DEBUG: <-- '250-SMTP Server 0.1 ESMTP Hello *******\n250-SIZE 20480000\n250 AUTH PLAIN LOGIN CRAM-MD5'
[2015-05-27 11:16:48] [MainThread] DEBUG: --> AUTH : 'PLAIN AGFkbWluADEyMzQ='
[2015-05-27 11:16:48] [MainThread] INFO: ('192.168.0.46', 52422) successfully authenticated
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '235 Authentication successful.'
[2015-05-27 11:16:48] [MainThread] DEBUG: --> MAIL : 'FROM:<reply@*******>'
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:48] [MainThread] DEBUG: --> RCPT : 'TO:<destination@*******>'
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:48] [MainThread] DEBUG: --> DATA
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '354 End data with <CR><LF>.<CR><LF>'
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '250 Ok'
[2015-05-27 11:16:48] [MainThread] DEBUG: --> QUIT
[2015-05-27 11:16:48] [MainThread] DEBUG: <-- '221 Bye'
但是当我添加这样的线程时:
def handle_accept(self):
pair = self.accept()
if pair is not None:
conn, addr = pair
logging.info('Incoming connection from ' + str(addr))
new_thread = threading.Thread(target=SMTPChannel, args=(config, conn, addr,))
new_thread.start()
日志如下所示:
kiril@kiril-X501A1 ~/www/py_email $ python SMTPServer.py
[2015-05-27 11:23:29] [MainThread] INFO: Server started at 192.168.0.103:1026
[2015-05-27 11:23:49] [MainThread] INFO: Incoming connection from ('192.168.0.46', 52414)
[2015-05-27 11:23:49] [Thread-1 ] DEBUG: <-- '220 SMTP Server 0.1 ESMTP'
[2015-05-27 11:23:49] [MainThread] DEBUG: --> EHLO : '*****'
[2015-05-27 11:23:49] [MainThread] DEBUG: <-- '250-SMTP Server 0.1 ESMTP Hello ********\n250-SIZE 20480000\n250 AUTH PLAIN LOGIN CRAM-MD5'
[2015-05-27 11:23:49] [MainThread] DEBUG: --> AUTH : 'PLAIN AGFkbWluADEyMzQ='
[2015-05-27 11:23:49] [MainThread] INFO: ('192.168.0.46', 52414) successfully authenticated
正如您所看到Thread-1
只触发一次,然后所有消息都会回到主线程......可能它有一些东西可以处理类扩展为class MerlinSMTPServer(asyncore.dispatcher):
和class SMTPChannel(asynchat.async_chat):
< / p>
答案 0 :(得分:1)
你不能混合asyncore
和这样的线程。 asyncore
/ asynchat
应用程序的重点是select
周围有一个事件循环来处理所有套接字,并调用各种处理程序。这一切都发生在一个线程上。请参阅asyncore
文档的介绍,该文档对此进行了解释。
在另一个线程上启动新的asynchat
频道没有任何好处。这只意味着它从另一个线程的事件循环中注册自己。 (这实际上并不是线程安全的,所以如果它有效,你就会变得幸运。)之后,事件循环和调度到通道的处理程序都发生在主线程上。
如果您想使用多线程,请不要使用asyncore
。如果您想使用asyncore
,请不要使用多线程。