簡體   English   中英

如何同時發送和接收數據 Python UDP socket

[英]How to send and receive data the same time Python UDP socket

最近剛了解#python,做了一個關於rasberry pi的小項目。 我想通過UDP協議在服務器之間傳輸和接收數據,客戶端是Ras,我使用Python的套接字庫。 將傳感器數據從 ras 傳輸到筆記本電腦,並將控制命令從筆記本電腦傳輸到 ras。 必須始終傳輸來自 ras 的數據,因此我使用了帶有 time.sleep 的 while true 循環。 問題又出在此時,來自筆記本電腦的控制命令並不總是發送,只在需要的時候發送,我在Ras上通過recvfrom()接收的控制命令也是在while True循環中,所以不發送控制命令的時候是 while true 循環卡在這里,因此無法再傳輸來自傳感器的數據。 mn幫我為這篇文章提供建議或關鍵詞。 謝謝你。

服務器.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("\n\n 2. Server received: ", data.decode('utf-8'), "\n\n")
    s.sendto(send_data.encode('utf-8'), address)
    print("\n\n 1. Server sent : ", send_data, "\n\n")
    time.sleep(1)

客戶端.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 命令端口進行阻塞讀取。 然后它可以將命令放入 Python Queue中,以便主程序隨時讀取,並且可以在超時的情況下進行讀取,這意味着當沒有傳入命令時主線程不會阻塞。 這里的描述很好,但代碼可能看起來像這樣:

#!/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 個端口。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM