繁体   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