簡體   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