作者uranusjr (←这人是超级笨蛋)
看板Python
标题Re: [问题] socketserver & ThreadingTCPServer
时间Mon Jun 13 02:18:37 2016
※ 引述《tyc5116 (累人啊....)》之铭言:
: 如题,有两个问题,参考官方的文件
: https://docs.python.org/3.3/library/socketserver.html
: 基本的通讯没问题,但有讯息截取的问题
: 官方文件是将接收到的文件直接print出来,我现在想要的是
: self.Server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
: self.m_thread_Monitor.start()-->会启动thread,
: 内有无限回圈执行server.serve_forever()
: ...
: aaa = server.getrecvdata()-->类似这样将server接收到的传出来
: print(aaa)
: 不知该如何修改?
: 以及另一个问题,我以为将上述的宣告改为
: self.Server =
: socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
: 会直接帮我们处理thread的问题,但是主视窗还是会卡住
: 请问该怎麽改?
我先确认一下
所以你的需求应该是, 有个 GUI 程式想跑一个 TCP server
然後想让它在背景跑(不会 block GUI thread)
并且把收到的东西传给别人(例如显示在视窗上)这样?
建议在问问题的时候直接讲你要什麽, 而不是问「这个东西要怎麽做」
因为你理解的解法可能根本就不对, 这样别人给你的建议也会完全错误
如果你直接说「想要什麽」与「现在有什麽」, 沟通会比较顺利
回到原本的问题, 假设你真的是要这两个东西
第一个需求的解法就是开 thread 来处理, 这个方向没错
但 ThreadingTCPServer 是会在每次呼叫 handle() 的时候开 thread(文件有提到)
虽然它的 handle() 不会 block GUI thread, 但在等 request 的时候仍然会
所以你需要的其实是把 serve_forever() 丢到 background thread 里面
这个其实文件也有提到怎麽做, 请看最後面那个 asynchronous 范例
第二个需求就比较麻烦一点, 因为你必须把收到的资料从背景传回 GUI thread
这通常会用 queue 来达成
https://docs.python.org/3/library/queue.html
你需要建立一个 queue, 然後在收到资料时丢给它
msg_q = queue.Queue()
class MyTCPRequestHandler(sockerserver.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024)
msg_q.put(data)
# 後略
然後在 GUI thread 从这个 queue 里面拿东西出来
要什麽时候拿就是个学问, 简单的方法可以用一个 timer 来做
例如 (以下假码, 请根据你用的 GUI framework 修改)
class MyWindow(gui.Window):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.timer = gui.Timer( # 每 0.1 秒呼叫 self.timeout
timeout=0.1,
callback=self.timeout,
repeat=True,
)
self.timer.start()
def timeout(self):
try: # 试着拿收到的资料出来, 如果没有就算了
data = msg_q.get_nowait()
except queue.Empty:
pass
else:
# 在这里把 data 显示到你要的地方
架构大概是长这样
剩下的就先试着自行参透吧
--
╱ ̄ ̄ ̄╲
▏
◢█◣ ▏
︻█︻█ ▏
成龙表示: 是喔...
′/ ‵ ▏
╰╯ █╱
ψQSWEET ◥︶█◤
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 218.161.94.175
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Python/M.1465755520.A.93A.html
※ 编辑: uranusjr (218.161.94.175), 06/13/2016 02:23:47
1F:推 tyc5116: msg_q是属於MyTCPRequestHandler or MyWindow的属性? 06/13 14:37
2F:→ tyc5116: 或是全域变数?这应该是我这个问题的主要疑问点 06/13 14:37
3F:→ uranusjr: 全域变数就可以了, 你要把它放进哪个 class 也没差, 只 06/13 15:27
4F:→ uranusjr: 要确定两个 queue 变数指向同一个 instance 就好 06/13 15:27