簡體   English   中英

收發使用 sockets python

[英]Sending and receiving using sockets python

我正在嘗試創建一個 function 來通過套接字客戶端和服務器發送和接收信息。 看來我的代碼在某種程度上被阻塞了。 在代碼中,我的 for 循環中的第一個命令迭代被執行,但隨后進程被阻塞。 有沒有人有任何建議如何使用線程或多線程來做到這一點?

我的代碼如下:

import socket
import json
import sys
import time
import select
import queue

Ni_Rio_IP= "172.22.11.2"
Ni_Base_IP= "172.22.11.1"

class AliceRio:

    def __init__(self, ip_rio, ip_pc):
        self.ip_rio = ip_rio
        AliceRio.udp_port_rio = 60006
        self.ip_pc = ip_pc
        AliceRio.udp_port_pc = 50005
        AliceRio.json= '{"Dest":"","Name":"","Time":"","Val":{"Str":[],"Pos":[[]],"Data":[[]]},"IP":0,"Port":0,"RT error":{"status":false,"code":0,"source":""}}'
        AliceRio.dict= json.loads(self.json)
    
    def PrintUDP(self):
        print("RIO IP: %s" % self.ip_rio)
        print("RIO UDP port: %s" % self.udp_port_rio)
        print("PC IP: %s" % self.ip_pc)
        print("PC UDP port: %s" % self.udp_port_pc)

    def SendRec(self, send_str):
        # Set up socket for sending
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Internet, UDP
        sock.sendto(bytes(send_str, 'utf-8'), (self.ip_rio, self.udp_port_rio))
        sock.close()
        print('got here')
        # Set up socket for receiving
        sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # Internet, UDP
        sock.bind((self.ip_pc, self.udp_port_pc))   
        rec_str, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
        print('got here2')
        sock.close()
        return rec_str
        
    def Receive(self, rec_str):
        sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # Internet, UDP
        sock.bind((self.ip_pc, self.udp_port_pc))   
        rec_str, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
        sock.close()
        return rec_str
        
    def Send(self, send_str):
        # Set up socket for sending
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Internet, UDP
        sock.sendto(bytes(send_str, 'utf-8'), (self.ip_rio, self.udp_port_rio))
        sock.close()
        #return rec_str
    
    def Aim(self, aim_perc):
        if aim_perc < 0 or aim_perc > 100: return "aim_perc out of range"
        send_dict=AliceRio.dict
        send_dict["Dest"]='Rio'
        send_dict["Name"]='Laser Control'
        Laser_Mode=1
        Simmer_A=0
        Pulse_A= 0
        Pulse_ms= 20
        
        send_dict["Val"]["Str"]=[str(Laser_Mode), str(aim_perc), str(Simmer_A), str(Pulse_A), str(Pulse_ms)]
        send_json=json.dumps(send_dict)
        
        # send it out
        self.SendRec(send_json)
        rec_json= self.SendRec(send_json)
        rec_dict=json.loads(rec_json)
        
        return "Aim laser now at " + rec_dict["Val"]["Str"][1] +'%' 

    def PWM_Laser_Fan(self, fan_perc):
        send_dict=AliceRio.dict
        send_dict["Dest"]='Rio'
        send_dict["Name"]='PWM Laser'       
        send_dict["Val"]["Str"][0]=str(fan_perc)
        send_json=json.dumps(send_dict)
     
        # send it out
        rec_json= self.SendRec(send_json)
        rec_dict=json.loads(rec_json)
        return rec_dict["Val"]["Str"][0]

    def Poll(self):
        send_dict=AliceRio.dict
        send_dict["Dest"]='Rio'
        send_dict["Name"]='Poll'       
        send_json=json.dumps(send_dict)
        # send it out
        rec_json= self.SendRec(send_json)
        rec_dict=json.loads(rec_json)
        
        if rec_dict["Val"]["Data"][0][0]==0: pid_mode='off' 
        else: pid_mode='PID' 
        print('PID mode:', pid_mode)
        print('Pos X:', rec_dict["Val"]["Data"][0][1])
        print('Pos Y:', rec_dict["Val"]["Data"][0][2])
        print('Home:', rec_dict["Val"]["Data"][0][3])
        print('Enabled:', rec_dict["Val"]["Data"][0][4])
    
    def PIDControl(self, pid_mode,pid_center):
        if pid_mode=="off": mode= 0
        elif pid_mode=="PID":mode =1
        else: return "pid_mode not valid"
        
        if pid_center[0] not in range(-2048,2048): return "center x-pos not in range"
        if pid_center[1] not in range(-2048,2048): return "center y-pos not in range"
    
        send_dict=AliceRio.dict
        send_dict["Dest"]='Rio'
        send_dict["Name"]='PID Control'
        send_dict["Val"]["Str"]=[str(mode), str(pid_center[0]), str(pid_center[1])]
        send_json=json.dumps(send_dict)
        # send it out
        rec_json= self.SendRec(send_json)
        rec_dict=json.loads(rec_json)
        return "PID mode now at " + rec_dict["Val"]["Str"][0]
           

Alice1 = AliceRio(Ni_Rio_IP, Ni_Base_IP)
Alice1.PrintUDP()

for i in range(10):
    Alice1.Aim((i*10)+10)
    time.sleep(0.2)

我建議學習使用Pdb並跟蹤程序的執行以找到它被捕獲的位置。

此外,在使用 sockets 學習/開發時,我發現在開始時為您的客戶端和服務器設置單獨的程序會有所幫助,因此您可以看到雙方如何處理交換而不是開始線程路由,因為日志記錄可能會變得混亂,祝你好運!

模塊線程在這種情況下確實有幫助。 我們可以創建一個線程來接收傳入的消息。 並且當收到新消息時,線程會觸發一個事件來通知等待方法SendRec

import sys
import socket
import json
import threading
import time


class AliceRio:

    def __init__(self, .....):
        
        # .........
        
        self.s_in = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.s_in.bind((self.ip_pc, self.udp_port_pc))
        self.evt = threading.Event()
        self.last_msg = None

    def _recv(self):
        while True:
            msg, _ = self.s_in.recvfrom(1024)
            self.last_msg = msg
            self.evt.set()

    def SendRec(self, send_str):
        if not hasattr(self, 'th_recv'):
            th = threading.Thread(target=self._recv)
            th.setDaemon(True)
            th.start()
            self.th_recv = th

        self.evt.clear()

        rio_endpoint = (self.ip_rio, self.udp_port_rio)
        s_out = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s_out.sendto(bytes(send_str, 'utf-8'), rio_endpoint)
        s_out.close()
        if self.evt.wait(timeout=15.0) and self.last_msg:
            return self.last_msg
        raise Exception('timeout waiting for response.')

暫無
暫無

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

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