多个 python UDP 套接字 & UI
multiple python UDP socket & UI
我是 python 的新手,仍处于阅读阶段。我这里有两个问题要讨论。我需要使用 tkinter
开发一个 python 基本用户界面,它应该在 Raspberry Pi2 上 运行。在后台进程中,我需要创建多个同样基于 python 的 UDP 套接字服务器和客户端。
我需要在用户按下任何按钮和select组合框中的任何值时将数据发送到 C++ 应用程序。同样,我需要使用从 C++ 应用程序收到的消息更新 UI。
我已经在 python 中创建了基本的 UI 和 UDP 套接字,它们按预期工作。现在我需要扩展它以便我可以将 UI 数据发送到 UDP 套接字脚本并从那里发送到 C++ 应用程序。
- 如何实例化多个UDP socket? python中是否有类似于FD_SET、select()的东西?
- 如何从 main.py 脚本启动 UI 和后台 UDP 套接字脚本?
- 如何指定像 canvas 这样的 c# 区域实现作为区域一,组合框作为区域二,按钮作为区域三,标签(labelframe)作为区域四,然后以不同的大小定位。
这是我的 python 代码:
from tkinter import *
from tkinter import ttk
class MainWindow(Frame):
def __init__(self):
Frame.__init__(self)
self.master.title("Test")
self.master.minsize(330, 400)
self.grid(sticky=E+W+N+S)
modeFrame = Frame(self)
actionFrame = Frame(self)
msgframe = Frame(self)
modeFrame.pack(side="top", fill="x")
actionFrame.pack(side="top", fill="x")
msgframe.pack(side="top", fill="x")
# Mode Frame
Label(modeFrame, text="Mode :", font="bold").pack(side="left")
modeFrame.canvas1 = Canvas(modeFrame, height=25, width=25)
modeFrame.setupled = modeFrame.canvas1.create_oval(5, 5, 20, 20, fill="green")
modeFrame.canvas1.pack(side="left")
Label(modeFrame, text="Setup Mode").pack(side="left")
modeFrame.canvas2 = Canvas(modeFrame, height=25, width=25)
modeFrame.setupled = modeFrame.canvas2.create_oval(5, 5, 20, 20, fill="black")
modeFrame.canvas2.pack(side="left")
Label(modeFrame, text="Run Mode").pack(side="left")
# Action Frame
Label(self, text="Select Coupon").pack(side="left")
self.value_of_combo = 'X'
self.combo("a,b,c")
Button(self, text="Accept", command=acceptCallback).pack(side="left")
Button(self, text="Reject", command=rejectCallback).pack(side="left")
Button(self, text="EndSession", command=endSessionCallback).pack(fill="both", expand="yes", side="bottom")
# Message Frame
self.label0frame = LabelFrame(msgframe, text="ID")
self.label0frame.pack(fill="both", expand="yes")
Label(self.label0frame, text="Waiting for Client ...").pack(side="left")
self.label1frame = LabelFrame(msgframe, text="Available Coupons")
self.label1frame.pack(fill="both", expand="yes")
Label(self.label1frame, text="Waiting for Client ...").pack(side="left")
self.label2frame = LabelFrame(msgframe, text="Scanned Code")
self.label2frame.pack(fill="both", expand="yes")
Label(self.label2frame, text="Scanned Code ...").pack(side="left")
self.label3frame = LabelFrame(msgframe, text="Status")
self.label3frame.pack(fill="both", expand="yes")
Label(self.label3frame, text="Status Message ...").pack(side="left")
def newselection(self, event):
self.value_of_combo = self.comboBox.get()
print(self.value_of_combo)
def combo(self,Values):
self.box_value = StringVar()
self.comboBox = ttk.Combobox(self, state="readonly", values=("a", "b", "c"))
self.comboBox.pack(side="left")
self.comboBox.set("a")
self.comboBox.bind("<<ComboboxSelected>>", self.newselection)
def acceptCallback():
print("send Accept Message to C++")
def rejectCallback():
print("send Reject Message to C++")
def endSessionCallback():
print("send EndSession Message to C++")
if __name__ == "__main__":
app = MainWindow()
app.mainloop()
UDP套接字代码:
import time
import struct
import socket
import sys
MYPORT = 51506
MYGROUP_4 = '225.0.0.1'
MYTTL = 1 # Increase to reach other networks
def UDPmain():
udpApp = udpsocket()
class udpsocket():
def __init__(self):
print('UDP Socket started')
group = MYGROUP_4
self.receiver('225.0.0.1')
def sender(group):
addrinfo = socket.getaddrinfo(group, None)[0]
s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
# Set Time-to-live (optional)
ttl_bin = struct.pack('@i', MYTTL)
if addrinfo[0] == socket.AF_INET: # IPv4
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl_bin)
else:
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl_bin)
while True:
data = repr(time.time())
s.sendto(data + '[=13=]', (addrinfo[4][0], MYPORT))
time.sleep(1)
def receiver(self,group):
print('Receiver')
# Look up multicast group address in name server and find out IP version
addrinfo = socket.getaddrinfo(group, None)[0]
# Create a socket
s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
# Allow multiple copies of this program on one machine
# (not strictly needed)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Bind it to the port
s.bind(('', MYPORT))
group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0])
# Join group
if addrinfo[0] == socket.AF_INET: # IPv4
mreq = group_bin + struct.pack('=I', socket.INADDR_ANY)
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
else:
mreq = group_bin + struct.pack('@I', 0)
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
# Loop, printing any data we receive
while True:
data, sender = s.recvfrom(1500)
while data[-1:] == '[=13=]': data = data[:-1] # Strip trailing [=13=]'s
print (str(sender) + ' ' + repr(data))
请看UI和我提到的评论
我很感激回答了整个问题的人。抱歉拖了这么久
Python 也可以使用 select
:请参阅 https://docs.python.org/3.4/library/select.html?highlight=select.select#select.select FD_SET
东西已为您处理;您只需提供文件描述符(或文件对象)列表。
这里有几个选项。一种是简单地将其他脚本直接合并到您的主代码中,并使用 multiprocessing
调用它们的入口点。 https://docs.python.org/3.4/library/multiprocessing.html?highlight=multiprocess#the-process-class 如果您想单独调用它们,还有其他选项,具体取决于您的操作系统 (os.spawn
、os.fork
+ os.execl
、subprocess
)
将 (3) 留给了解 tkinter
东西的其他人。
我是 python 的新手,仍处于阅读阶段。我这里有两个问题要讨论。我需要使用 tkinter
开发一个 python 基本用户界面,它应该在 Raspberry Pi2 上 运行。在后台进程中,我需要创建多个同样基于 python 的 UDP 套接字服务器和客户端。
我需要在用户按下任何按钮和select组合框中的任何值时将数据发送到 C++ 应用程序。同样,我需要使用从 C++ 应用程序收到的消息更新 UI。
我已经在 python 中创建了基本的 UI 和 UDP 套接字,它们按预期工作。现在我需要扩展它以便我可以将 UI 数据发送到 UDP 套接字脚本并从那里发送到 C++ 应用程序。
- 如何实例化多个UDP socket? python中是否有类似于FD_SET、select()的东西?
- 如何从 main.py 脚本启动 UI 和后台 UDP 套接字脚本?
- 如何指定像 canvas 这样的 c# 区域实现作为区域一,组合框作为区域二,按钮作为区域三,标签(labelframe)作为区域四,然后以不同的大小定位。
这是我的 python 代码:
from tkinter import *
from tkinter import ttk
class MainWindow(Frame):
def __init__(self):
Frame.__init__(self)
self.master.title("Test")
self.master.minsize(330, 400)
self.grid(sticky=E+W+N+S)
modeFrame = Frame(self)
actionFrame = Frame(self)
msgframe = Frame(self)
modeFrame.pack(side="top", fill="x")
actionFrame.pack(side="top", fill="x")
msgframe.pack(side="top", fill="x")
# Mode Frame
Label(modeFrame, text="Mode :", font="bold").pack(side="left")
modeFrame.canvas1 = Canvas(modeFrame, height=25, width=25)
modeFrame.setupled = modeFrame.canvas1.create_oval(5, 5, 20, 20, fill="green")
modeFrame.canvas1.pack(side="left")
Label(modeFrame, text="Setup Mode").pack(side="left")
modeFrame.canvas2 = Canvas(modeFrame, height=25, width=25)
modeFrame.setupled = modeFrame.canvas2.create_oval(5, 5, 20, 20, fill="black")
modeFrame.canvas2.pack(side="left")
Label(modeFrame, text="Run Mode").pack(side="left")
# Action Frame
Label(self, text="Select Coupon").pack(side="left")
self.value_of_combo = 'X'
self.combo("a,b,c")
Button(self, text="Accept", command=acceptCallback).pack(side="left")
Button(self, text="Reject", command=rejectCallback).pack(side="left")
Button(self, text="EndSession", command=endSessionCallback).pack(fill="both", expand="yes", side="bottom")
# Message Frame
self.label0frame = LabelFrame(msgframe, text="ID")
self.label0frame.pack(fill="both", expand="yes")
Label(self.label0frame, text="Waiting for Client ...").pack(side="left")
self.label1frame = LabelFrame(msgframe, text="Available Coupons")
self.label1frame.pack(fill="both", expand="yes")
Label(self.label1frame, text="Waiting for Client ...").pack(side="left")
self.label2frame = LabelFrame(msgframe, text="Scanned Code")
self.label2frame.pack(fill="both", expand="yes")
Label(self.label2frame, text="Scanned Code ...").pack(side="left")
self.label3frame = LabelFrame(msgframe, text="Status")
self.label3frame.pack(fill="both", expand="yes")
Label(self.label3frame, text="Status Message ...").pack(side="left")
def newselection(self, event):
self.value_of_combo = self.comboBox.get()
print(self.value_of_combo)
def combo(self,Values):
self.box_value = StringVar()
self.comboBox = ttk.Combobox(self, state="readonly", values=("a", "b", "c"))
self.comboBox.pack(side="left")
self.comboBox.set("a")
self.comboBox.bind("<<ComboboxSelected>>", self.newselection)
def acceptCallback():
print("send Accept Message to C++")
def rejectCallback():
print("send Reject Message to C++")
def endSessionCallback():
print("send EndSession Message to C++")
if __name__ == "__main__":
app = MainWindow()
app.mainloop()
UDP套接字代码:
import time
import struct
import socket
import sys
MYPORT = 51506
MYGROUP_4 = '225.0.0.1'
MYTTL = 1 # Increase to reach other networks
def UDPmain():
udpApp = udpsocket()
class udpsocket():
def __init__(self):
print('UDP Socket started')
group = MYGROUP_4
self.receiver('225.0.0.1')
def sender(group):
addrinfo = socket.getaddrinfo(group, None)[0]
s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
# Set Time-to-live (optional)
ttl_bin = struct.pack('@i', MYTTL)
if addrinfo[0] == socket.AF_INET: # IPv4
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl_bin)
else:
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl_bin)
while True:
data = repr(time.time())
s.sendto(data + '[=13=]', (addrinfo[4][0], MYPORT))
time.sleep(1)
def receiver(self,group):
print('Receiver')
# Look up multicast group address in name server and find out IP version
addrinfo = socket.getaddrinfo(group, None)[0]
# Create a socket
s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
# Allow multiple copies of this program on one machine
# (not strictly needed)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Bind it to the port
s.bind(('', MYPORT))
group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0])
# Join group
if addrinfo[0] == socket.AF_INET: # IPv4
mreq = group_bin + struct.pack('=I', socket.INADDR_ANY)
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
else:
mreq = group_bin + struct.pack('@I', 0)
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
# Loop, printing any data we receive
while True:
data, sender = s.recvfrom(1500)
while data[-1:] == '[=13=]': data = data[:-1] # Strip trailing [=13=]'s
print (str(sender) + ' ' + repr(data))
请看UI和我提到的评论
我很感激回答了整个问题的人。抱歉拖了这么久
Python 也可以使用
select
:请参阅 https://docs.python.org/3.4/library/select.html?highlight=select.select#select.selectFD_SET
东西已为您处理;您只需提供文件描述符(或文件对象)列表。这里有几个选项。一种是简单地将其他脚本直接合并到您的主代码中,并使用
multiprocessing
调用它们的入口点。 https://docs.python.org/3.4/library/multiprocessing.html?highlight=multiprocess#the-process-class 如果您想单独调用它们,还有其他选项,具体取决于您的操作系统 (os.spawn
、os.fork
+os.execl
、subprocess
)
将 (3) 留给了解 tkinter
东西的其他人。