2014-12-07 67 views
0

我遇到了一个问题,从Arduino接收数据(一串文本)通过C#Winform应用程序。 Arduino的草图基本上回复我发送的任何内容。我能够发送数据。奇怪的是,如果我远程登录设备并键入它正确地响应,因此出现的问题是我的C#代码的任何文字,但我似乎无法弄清楚我在哪里不正确。Arduino以太网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; 
    }  
} 
} 
} 

回答

1

您的代码有许多事情不对的地方,包括哪些已经是最常见的新手在任何情况下我都看到错误:你没有考虑到实际上读取的字节数。另外,你还有另一个主题变化,就是你处理整个接收缓冲区数组,就好像整个事物都有有效数据一样。

没有办法测试,很难确定。但最起码,你应该改变你接受的方法是这样的:

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属性值
  • DO捕获和读操作
  • 不要串联空字符串与其他字符串(即使是在一个迭代场景中使用的返回值,人们应该使用StringBuilder代替,在这里你甚至没有迭代级联!)

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

请注意,上述仅仅改进了代码。即使上述方法仍然存在“我在任何上下文中看到的最常见的新手错误”的变体:尽管它使用了读操作的返回值,但它并没有完成它所做的任何事情。特别是:

  1. 实际上并不保证您会收到在一次读取操作中发送给您的所有字节。这意味着你的应用协议确实应该有一些方法可以让你你正在读其中一个消息结束和下一个开始字节流中识别。
  2. 当连接正常关闭,读取操作将返回0作为字节数,此时自己的代码应该由完成了什么写你需要(如果有的话),然后优雅地关闭套接字响应通过调用Socket.Shutdown(SocketShutdown.Both)和最终Socket.Close()您自己的套接字。

但上面至少应该帮助您在您的项目推进进度。

你真的应该改变恕我直言,我没有打扰在上面的另一件事是,你不应该使用实例字段(即readData)传递数据时,只需传递它作为方法参数就足够了。你应该避免side-effects in your code尽可能。这将使得代码更容易理解,从而正确地写,等等。

+0

中肯的批评,但我必须说,这仅仅是一个考验。我不是熟悉的Arduino和图书馆,我只是想炼代码之前得到一些数据从设备后部。无意义的嵌套而循环确实是一个疏忽。我不能相信我错过了这一点。我知道我需要检查消息何时结束。我做在硬件上,但是,从我的C#测试删除它。再次感谢您的建议。 – 2014-12-07 18:59:53

相关问题