如果您不知道要传输多少数据,如何接收套接字信息?

如何解决如果您不知道要传输多少数据,如何接收套接字信息?

| 我正在基于Python的GUI界面上与运行Python的机器人以及作为电机控制器和传感器控制器的Arduino Mega进行交互。 最初,我打算使用远程桌面从机器人加载GUI。事实证明,由于使用远程桌面,这非常慢。我认为服务器和客户端会更好。 我有一个在我的Arduino上运行的草图,它可以捕获电动机命令并执行它们。它还等待“ Ping”命令通过,这时应该检查超声波传感器在三个不同位置,然后将此信息写回到服务器,服务器应捕获此数据并将其传递给客户端GUI。我已经将其全部工作了,但似乎无法将数据从服务器返回到客户端。我曾以为,简单的\“ client.recv()\”可以完成此操作,但事实并非如此。 如果我不知道到底要返回多少数据,我该如何接收这些数据? Arduino将数据发送为\“ dist1,dist2,dist3 \\ n \”。 这是我的Arduino代码:
#include <LiquidCrystal.h>
#include <Ping.h>
#include <Servo.h>
// Parallax Ping Unit for distance sensing.
Ping sonic(22);

// Setup LCD pins.
LiquidCrystal lcd(7,8,9,10,11,12);

// Servo for Ping unit sweeping.
Servo  PingServo;

// Setup Ping distance setting variables.
int pingDisCent;
int pingDisLeft;
int pingDisRight;

// Variable to keep commands in.
char MsgRcvd;

// Motor setup information.

int LF[] = {23,24};
int LR[] = {25,26};
int RF[] = {27,28};
int RR[] = {29,30};

// Set Debugging here
// 1 - Debug on - Motors don\'t turn when commands are sent.
// 0 - Debug off - Motors turn when commands are sent.
int debug = 1;

//Variables for speed
int SpdPin = 22;
int Speed = 255;

void setup()
{
  Serial.begin(9600);  // start serial communications

  // Setup motors for output.
  int i;
  for(i = 0; i < 2; i++){
    pinMode(LF[i],OUTPUT);
    pinMode(LR[i],OUTPUT);
    pinMode(RF[i],OUTPUT);
    pinMode(RR[i],OUTPUT);
  }

  // Setup servo to sweep.
  PingServo.attach(6);
  PingServo.write(90);

  // Set up the LCD\'s number of rows and columns:
  lcd.begin(16,2);

  // Print a message to the LCD.
  lcd.print(\"Waiting...\");

  // Setup speed pin.
  pinMode(SpdPin,OUTPUT);
}

void loop()
{
  if (Serial.available() > 0)    //Check to see if a command is available.
  {
    MsgRcvd = Serial.read();    // If a command is there,see what it is.
    switch (MsgRcvd)
    {
      case \'0\':
        Stop();
        break;
      case \'1\':
        MoveForward();
        break;
      case \'2\':
        MoveLeft();
        break;
      case \'3\':
        MoveRight();
        break;
      case \'4\':
        MoveBackward();
        break;
      case \'~\':
        active_ir();
        break;
      case \'M\':                    // Check to see if we have a connection from the GUI - if so spit out information to the LCD.
        lcd.clear();
        lcd.print(\"Connected\");
        lcd.setCursor(0,1);
        lcd.print(\"waiting..\");
        break;
      case \'D\':
        lcd.setCursor(0,1);
        lcd.print(\"Disconnected\"); // Client disconnected - spit out a disconnect to the LCD.
        break;
    }
  }
  delay(100);
}

//  ===================================
//  =====    Ping Ultrasonic      =====
//  ===================================
void active_ir()
{
  // Read to the right.
  PingServo.write(30);
  delay(300);
  pingDisRight = sonic.inch();
  delay(500);

  // Read to the front.
  PingServo.write(90);
  delay(300);
  pingDisCent = sonic.inch();
  delay(500);
  //  Read to the left.
  PingServo.write(150);
  delay(300);
  pingDisLeft = sonic.inch();
  delay(500);
  Serial.print(pingDisLeft);
  Serial.print(\',\');
  Serial.print(pingDisCent);
  Serial.print(\',\');
  Serial.println(pingDisRight);
  return;
}



//  ==========================================
//  ======        MOTOR CONTROL      =========
//  ==========================================

void MoveForward()
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(\"Forward\");
  if (debug == 0){

    digitalWrite(LF[0],HIGH);
    digitalWrite(LF[1],LOW);
    digitalWrite(LR[0],HIGH);
    digitalWrite(LR[1],LOW);
    digitalWrite(RF[0],HIGH);
    digitalWrite(RF[1],LOW);
    digitalWrite(RR[0],HIGH);
    digitalWrite(RR[1],LOW);
  }
}

void MoveBackward()
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(\"Reverse\");
  if (debug == 0){
    analogWrite(SpdPin,Speed);
    digitalWrite(LF[0],LOW);
    digitalWrite(LF[1],HIGH);
    digitalWrite(LR[0],LOW);
    digitalWrite(LR[1],HIGH);
    digitalWrite(RF[0],LOW);
    digitalWrite(RF[1],HIGH);
    digitalWrite(RR[0],LOW);
    digitalWrite(RR[1],HIGH);
  }
}

void MoveLeft()
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(\"Left\");
  if (debug == 0){
    analogWrite(SpdPin,LOW);
  }
}

void MoveRight()
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(\"Right\");
  if (debug == 0) {
    analogWrite(SpdPin,HIGH);
  }
}

void Stop()
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(\"Stopping\");
  if (debug == 0){
    digitalWrite(LF[0],LOW);
  }
}
这是我的Python服务器代码:
import serial
import socket

Serv = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
Serv.bind((\'\',9000))
Serv.listen(1)
print \"Listening on TCP 9000\"
motor = serial.Serial(\'/dev/ttyUSB0\',9600,timeout=1)
print \"Connected to Motor Controller: /dev/ttyUSB0\"

while(1):
    print \"Waiting For Connection...\"
    connection,addr = Serv.accept()
    connection.setblocking(0)
    print \"Connected by\",addr[0]
    while(1):
        try:
            Servdata = connection.recv(1)
            break
        except:
            pass
    if (Servdata == \'M\'):
        print \"Entering Manual Mode\"
        motor.write(Servdata)
        while(Servdata != \'X\'):
            Servdata = \'9\'
            try:
                Servdata = connection.recv(1)
            except:
                pass
            if Servdata == \'X\':
                print \"Exiting\"
                break
            if Servdata == \'0\':
                print \"Stopping\"
                motor.write(Servdata)
            if Servdata == \'1\':
                print \"Forward\"
                motor.write(Servdata)
            if Servdata == \'2\':
                print \"Left\"
                motor.write(Servdata)
            if Servdata == \'3\':
                print \"Right\"
                motor.write(Servdata)
            if Servdata == \'4\':
                motor.write(Servdata)
                print \"Backwards\"
            if Servdata == \'~\':
                motor.write(Servdata)
                retval = motor.readline()
                Serv.send(retval)
            else:
                pass
        motor.write(\'0\')
        connection.close()
        print addr[0],\"Closed Manual Mode\"
最后但并非最不重要的一点是,客户端GUI代码(这也是我认为问题所在的地方...):
from socket import *
from PythonCard import model
HOST = \'\'
PORT = 9000
ADDR = (HOST,PORT)
BUFSIZE = 4096
Client = socket (AF_INET,SOCK_STREAM)
Client.connect((ADDR))
Client.send(\'M\')
class MainWindow(model.Background):
    def on_SetSpdBtn_mouseClick(self,event):
        spd = self.components.SpdSpn.value
    def on_FwdBtn_mouseClick(self,event):
        spd = self.components.SpdSpn.value
        Client.send(\'1\')
    def on_LftBtn_mouseClick(self,event):
        spd = self.components.SpdSpn.value
        Client.send(\'2\')
    def on_RitBtn_mouseClick(self,event):
        spd = self.components.SpdSpn.value
        Client.send(\'3\')
    def on_RevBtn_mouseClick(self,event):
        spd = self.components.SpdSpn.value
        Client.send(\'4\')
    def on_StpBtn_mouseClick(self,event):
        spd = self.components.SpdSpn.value
        Client.send(\'0\')
    def on_GetPing_mouseClick(self,event):
        Client.send(\'~\')
        retval = Client.recv()
        ping_data = retval.strip() # Strip out the newline,if you read an entire line.
        split_data = ping_data.split(\',\')
        L_Ping = split_data[0]
        R_Ping = split_data[1]
        self.components.PingLeft.text = str(L_Ping)
        self.components.PingRight.text = str(R_Ping)
app = model.Application(MainWindow)
app.MainLoop()
    

解决方法

        我想我在这段代码中发现了三个问题;第一个是浪费,第二个可能是您今天来这里的原因,第三个是您认为今天来这里的原因。 :) 忙碌中 此代码正忙于等待数据进入连接:
connection.setblocking(0)
print \"Connected by\",addr[0]
while(1):
    try:
        Servdata = connection.recv(1)
        break
    except:
        pass
再次在这里:
    while(Servdata != \'X\'):
        Servdata = \'9\'
        try:
            Servdata = connection.recv(1)
        except:
            pass
        # ...
        else:
            pass
如此疯狂地消耗CPU周期。希望您不要依靠电池供电。它也不会买任何东西。您最好将阻塞叫
recv()
。等待下一个输入字节时让CPU进入睡眠状态。 (如果您实际上在对任何内容使用非阻塞,那么忙碌的等待会更有意义,但是您没有。如果您想限制服务器阻塞输入的时间,总会有
settimeout()
。但是也不要盲目地使用它,因为仅从切换到阻止
recv()
,此代码将受益最大。) 不向客户端发送数据
        if Servdata == \'~\':
            motor.write(Servdata)
            retval = motor.readline()
            Serv.send(retval)
我认为此代码块尚未执行:)
Serv
未连接任何东西,它是一个监听套接字。您在这里的意思是10英镑。我在服务器中找不到任何其他行,这些行实际上会将数据发送到客户端,因此大概应该是这样。 一次全部 客户端中的这段代码有些脆弱,但可能永远不会中断:
def on_GetPing_mouseClick(self,event):
    Client.send(\'~\')
    retval = Client.recv()
    ping_data = retval.strip() # strip out the newline,if you read an entire line
    split_data = ping_data.split(\',\')
    L_Ping = split_data[0]
    R_Ping = split_data[1]
    self.components.PingLeft.text = str(L_Ping)
    self.components.PingRight.text = str(R_Ping)
该代码假定“ 5”调用将恰好返回一个协议消息。 TCP流无法正常工作,对等方可以随意发送任意大小的传出数据。 (TCP / IP堆栈始终将多个应用程序级别的消息组合到一个TCP数据包中。它们还会发送小于请求的数据包,以避免分段。) 更安全的方法是使用从远程对等方接收的内容填充队列,然后解析该队列以获取命令/消息。您可能在队列中找到十个命令,可能只找到一部分命令-但是您的代码需要准备好将部分消息推送到队列中,并在可用时使用队列中的完整消息。 这是一些额外的工作,但是在不太理想的情况下安全操作是必需的。您可能永远不会在LAN上遇到问题,但是当您进行无线连接或通过较大的网络路由时会遇到麻烦。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-