繁体   English   中英

Arduino以太网C#客户端未接收到数据

[英]Arduino ethernet c# client not receiving data

我在通过C#Winform应用程序从Arduino接收数据(文本字符串)时遇到问题。 Arduino上的草图基本上可以用我发送的内容进行回复。 我能够发送数据。 奇怪的是,如果我对设备进行telnet并输入任何可正确响应的文本,那么看来问题出在我的C#代码上,但是,我似乎无法弄清楚我的错误所在。

这是我所拥有的

public partial class Form1 : Form
{

    System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
    NetworkStream serverStream = default(NetworkStream);
    string readData = null;


    public Form1()
    {
        InitializeComponent();

    }

    private void button1_Click(object sender, EventArgs e)
    {
        byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textBox2.Text);
        serverStream.Write(outStream, 0, outStream.Length);
        serverStream.Flush();
    }


    private void button2_Click(object sender, EventArgs e)
    {

        clientSocket.Connect("192.168.1.177", 5223);
        readData = "Conected Arduino ...";
        msg();
        serverStream = clientSocket.GetStream();
        byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textBox2.Text);
        serverStream.Write(outStream, 0, outStream.Length);
        serverStream.Flush();

        Thread ctThread = new Thread(getData);
        ctThread.Start();
    }



    private void getData()
    {

        while (true)
        {

            while (true)
            {
                serverStream = clientSocket.GetStream();
                int buffSize = clientSocket.ReceiveBufferSize;
                byte[] inStream = new byte[10025];
                serverStream.Read(inStream, 0, buffSize);
                string returndata = System.Text.Encoding.ASCII.GetString(inStream);
                readData = "" + returndata;
                msg();
            }

        }
    }

    private void msg()
    {

        this.BeginInvoke(new Action(() =>
        {
            textBox1.Text = String.Format("{0}{1} >> {2}", textBox1.Text, Environment.NewLine, readData);
        }
    ));
    }


}

这是Arduino草图的一部分

void loop() {
// wait for a new client:
EthernetClient client = server.available();

// when the client sends the first byte, say hello:
if (client) {
if (!alreadyConnected) {
  // clead out the input buffer:
  client.flush();    
  Serial.println("We have a new client");
  client.println("Hello, client!");
  alreadyConnected = true;
}

if (client.available() > 0) {
  // read the bytes incoming from the client:
  char thisChar = client.read();
  // echo the bytes back to the client:
  //server.write(thisChar);
  // echo the bytes to the server as well:
  //Serial.write(thisChar);
   if (inputPos < maxLength-1) 
   { 
    if (thisChar == '\n') 
        {
            inputString[inputPos] = 0;
                            server.write(inputString);
            Serial.write(inputString);
            inputPos = 0;
        } else {
                // add it to the inputString:
            inputString[inputPos] = thisChar;
            inputPos++;
        }
   } else {
     inputPos = 0;
   }      
}
}
}

您的代码有很多问题,包括我在任何情况下看到的最常见的新手错误:您没有考虑实际读取的字节数。 另外,您在主题上还有另一个共同的变体,那就是您像处理整个接收缓冲区阵列中的有效数据一样处理整个接收缓冲区阵列。

没有测试的方法,很难确定。 但是至少,您应该将接收方法更改为如下所示:

private void getData()
{
    serverStream = clientSocket.GetStream();

    while (true)
    {
        byte[] inStream = new byte[10025];
        int bytesRead = serverStream.Read(inStream, 0, inStream.Length);
        readData = System.Text.Encoding.ASCII.GetString(inStream, 0, bytesRead);
        msg();
    }
}
  • 切勿毫无意义巢while (true)另一个内部循环while (true)
  • 每次阅读时都不要创建新的NetworkStream
  • 与关心自己Socket.ReceiveBufferSize属性值
  • 必须捕获并使用读取操作中的返回值
  • 不要将空字符串与其他字符串连接在一起(即使在迭代的情况下,也应该使用StringBuilder ,并且这里甚至没有迭代连接!)

当然,并非所有这些缺陷都是致命的。 最大的问题是每次读取都需要新的NetworkStream以及接收缓冲区和结果值的管理不当。 但实际上,您应该努力使所有代码都变得更好。

注意,以上仅改进了代码。 即使以上内容仍对“我在任何情况下都遇到过的最常见的新手错误”有所不同:尽管它确实使用了读取操作的返回值,但并没有尽其所能。 尤其是:

  1. 实际上,不能保证您将通过一次读取操作接收到发送给您的所有字节。 这意味着您的应用程序协议确实应该有某种方式可以让您在正在读取的字节流中识别一条消息的结尾和下一条消息的开始。
  2. 当连接正常关闭时,读取操作将返回0作为字节数,这时您自己的代码应该通过完成对套接字的所有写操作(如果有)来响应,然后优雅地关闭自己的套接字通过调用Socket.Shutdown(SocketShutdown.Both)并最终Socket.Close()

但是以上内容至少应该帮助您在项目中取得进步。

您确实应该更改IMHO的另一件事,而我在上面没有打扰,那就是当简单地将它作为方法参数就足够时,您不应使用实例字段(即readData )来传递数据。 您应该尽可能避免代码中的副作用 这将使代码更易于理解,从而可以正确编写代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM