如何同时发送和接收数据Python UDP套接字



我最近刚刚学习了#python,我做了一个关于raspberry pi的小项目。我想在服务器是笔记本电脑,客户端是Ras之间通过UDP协议传输和接收数据,我使用Python的套接字库。将传感器数据从ras传输到笔记本电脑,并将控制命令从笔记本电脑传输到ras。来自ras的数据必须始终传输,所以我使用了一个带有time.sleep的while true循环。问题再次出现在这一点上,来自笔记本电脑的控制命令并不总是发送,仅在必要时发送,我通过recvfrom()接收Ras上的控制命令也在True循环中,因此,当不传输控制命令时,是在这里卡住的True循环,因此来自传感器的数据无法再传输。请帮我给这篇文章一些建议或关键词。谢谢你。

server.py

import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ip = ""
port = 5001
server_address = (ip, port)
s.bind(server_address)
while True:
print("####### Server is listening #######")
data, address = s.recvfrom(4096)
print("nn 2. Server received: ", data.decode('utf-8'), "nn")
s.sendto(send_data.encode('utf-8'), address)
print("nn 1. Server sent : ", send_data, "nn")
time.sleep(1)

cilent.py

import time
import socket
import random
UDP_IP = ""
UDP_PORT = 5001
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM, 0)
while True:
roll = random.randrange(1,100)
a = str(roll)
s.sendto(a.encode('utf-8'), (UDP_IP, UDP_PORT))
print("data gui:",str(roll).encode('utf-8'))
data, address = s.recvfrom(4096)
print("data nhan",data)
time.sleep(1)

如果从RasPi发送数据到PC是一个必须始终运行的相当独立的事情,您可以考虑为它创建一个单独的执行线程,这样您就可以在那里sleep()并且通常做任何您想做的事情,而不会干扰接收您必须响应的偶尔命令。这里有一个很好的线程描述,但它可能看起来像这样:

#!/usr/bin/env python3
import sys
import time
import random
import logging
import threading, queue

def Transmitter():
"""Transmits readings to PC at 1 second intervals on a separate thread"""
logging.debug(f'[Transmitter] Starting')
# Start independent loop sending values
i = 0
while True:
reading = random.randint(0,100)
logging.debug(f'[Transmitter] Iteration: {i}, reading: {reading}')
i += 1
time.sleep(1)
if __name__ == '__main__':
# Set up logging - very advisable with threaded code
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s %(message)s')
# Create independent thread to transmit readings
thr = threading.Thread(target=Transmitter, args=())
thr.start()
# Main loop - waiting for commands from PC
logging.debug('[Main] Starting main loop')
i = 0
while True:
# Not what you want but just showing the other thread is unaffacted by sleeping here
time.sleep(5)
i += 1
logging.debug(f'[Main] Iteration: {i}')

下面是示例运行的输出:

DEBUG [Transmitter] Starting
DEBUG [Transmitter] Iteration: 0, reading: 82
DEBUG [Main] Starting main loop
DEBUG [Transmitter] Iteration: 1, reading: 84
DEBUG [Transmitter] Iteration: 2, reading: 45
DEBUG [Transmitter] Iteration: 3, reading: 47
DEBUG [Transmitter] Iteration: 4, reading: 97
DEBUG [Main] Iteration: 1
DEBUG [Transmitter] Iteration: 5, reading: 81
DEBUG [Transmitter] Iteration: 6, reading: 20
DEBUG [Transmitter] Iteration: 7, reading: 6
DEBUG [Transmitter] Iteration: 8, reading: 16
DEBUG [Transmitter] Iteration: 9, reading: 54
DEBUG [Main] Iteration: 2
DEBUG [Transmitter] Iteration: 10, reading: 67
DEBUG [Transmitter] Iteration: 11, reading: 91
DEBUG [Transmitter] Iteration: 12, reading: 37
同样,如果你不想让挂起/阻塞在RasPi上等待来自PC的命令,你可以启动另一个线程,它位于一个紧循环中,从UDP命令端口进行阻塞读取。然后,它可以将命令放入PythonQueue中供主程序随时读取,并且可以在超时时执行读取,这意味着主线程在没有传入命令时不会阻塞。这里的描述很好,但代码可能看起来像这样:
#!/usr/bin/env python3
import sys
import time
import random
import logging
import threading, queue
def Transmitter():
"""Transmits readings to PC at 1 second intervals"""
logging.debug(f'[Transmitter] Starting')
# Start independent loop sending values
i = 0
while True:
reading = random.randint(0,100)
logging.debug(f'[Transmitter] Iteration: {i}, reading: {reading}')
i += 1
time.sleep(1)
def Receiver(Q):
"""Waits for commands and queues them to the main process"""
logging.debug(f'[Receiver] Starting')
# Wait for commands from PC and place into queue
while True:
# We will actually wait a random number of seconds and then synthesize dummy command
time.sleep(random.randint(3,7))
cmd = f'command_{random.randint(100,200)}'
logging.debug(f'[Receiver] Synthesizing cmd: {cmd}')
Q.put(cmd)
if __name__ == '__main__':
# Set up logging - very advisable with threaded code
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s %(message)s')
# Create independent thread to transmit readings
tx = threading.Thread(target=Transmitter, args=())
tx.start()
# Create independent thread to receive commands and send to us via queue
Q = queue.Queue()
rx = threading.Thread(target=Receiver, args=(Q,))
rx.start()
# Main loop - processing commands from queue
logging.debug('[Main] Starting main loop')
msgNum = 0
while True:
# Wait for a message from queue...
# ... you can either block like I am here
# ... or use timeout and not block
cmd = Q.get()
msgNum += 1
logging.debug(f'[Main] Received cmd: {cmd} {msgNum}')

注意:我不相信Python套接字是线程安全的,所以你可能想用这种方法在不同的端口上发送和接收——但这应该不是问题,因为有65,000个端口。

最新更新