简体   繁体   English

收发使用 sockets python

[英]Sending and receiving using sockets python

I am trying to create a function to send and receive information over a socket client & server.我正在尝试创建一个 function 来通过套接字客户端和服务器发送和接收信息。 It appears that my code is somehow blocking.看来我的代码在某种程度上被阻塞了。 In the code the first command iteration in my for loop is carried out but then the process becomes blocked.在代码中,我的 for 循环中的第一个命令迭代被执行,但随后进程被阻塞。 Does anyone have any suggestions how to do this using threading or multithreading?有没有人有任何建议如何使用线程或多线程来做到这一点?

My code is below:我的代码如下:

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)

I would suggest learning to use Pdb and trace through the execution of your program to find where it is getting caught.我建议学习使用Pdb并跟踪程序的执行以找到它被捕获的位置。

Also when learning/developing with sockets I've found that it helps to have separate programs for your client and server in the beginning so you can see how both sides are handling exchanges instead of going the threading route to start since the logging can get confusing, best of luck!此外,在使用 sockets 学习/开发时,我发现在开始时为您的客户端和服务器设置单独的程序会有所帮助,因此您可以看到双方如何处理交换而不是开始线程路由,因为日志记录可能会变得混乱,祝你好运!

Module threading does help in this scenario.模块线程在这种情况下确实有帮助。 We can create a thread to receiving incoming messages.我们可以创建一个线程来接收传入的消息。 And when new message received the thread trigger an event to notify the waiting method SendRec .并且当收到新消息时,线程会触发一个事件来通知等待方法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