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

Arduino以太网c#客户端未接收数据,c#,network-programming,arduino,ethernet,C#,Network Programming,Arduino,Ethernet,我在通过C#Winform应用程序从Arduino接收数据(文本字符串)时遇到问题。Arduino号上的草图基本上回复了我发送的任何内容。我能够发送数据。奇怪的是,如果我远程登录设备并键入任何文本,它会正确响应,因此问题似乎是我的C#代码,然而,我似乎无法找出我的错误所在 这是我的 public partial class Form1 : Form { System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.

我在通过C#Winform应用程序从Arduino接收数据(文本字符串)时遇到问题。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);
        }
    ));
    }


}
这是阿杜伊诺草图的一部分

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;
   }      
}
}
}
void循环(){
//等待新客户端:
EthernetClient=server.available();
//当客户端发送第一个字节时,打招呼:
如果(客户){
如果(!已连接){
//清除输入缓冲区:
client.flush();
Serial.println(“我们有一个新客户”);
println(“你好,客户!”);
alreadyConnected=true;
}
if(client.available()>0){
//读取从客户端传入的字节:
char thisChar=client.read();
//将字节回显到客户端:
//server.write(thisChar);
//将字节也回显到服务器:
//Serial.write(thisChar);
如果(输入位置<最大长度-1)
{ 
如果(thisChar=='\n')
{
inputString[inputPos]=0;
server.write(inputString);
串行写入(输入字符串);
inputPos=0;
}否则{
//将其添加到inputString:
inputString[inputPos]=此字符;
inputPos++;
}
}否则{
inputPos=0;
}      
}
}
}

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

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

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
,以及接收缓冲区和结果值管理不当。但实际上,您应该努力使所有代码都是好的

请注意,以上只是改进了代码。即使是上面提到的“我在任何上下文中看到的最常见的新手错误”也有一个变体:虽然它确实使用读取操作的返回值,但它并没有完成它应该做的一切。特别是:

  • 实际上并不能保证在一次读取操作中收到发送给您的所有字节。这意味着您的应用程序协议真的应该有某种方式让您在正在读取的字节流中识别一条消息的结束位置和下一条消息的开始位置
  • 当连接正常关闭时,读取操作将返回0作为字节计数,此时您自己的代码应该通过完成对套接字的任何写入(如果有)来响应,然后通过调用
    socket.Shutdown(SocketShutdown.Both)正常关闭您自己的套接字
    最后是
    Socket.Close()
  • 但以上内容至少可以帮助您在项目中取得进展

    还有一件事你真的应该改变IMHO,我在上面没有提及,那就是你不应该使用一个实例字段(即,
    readData
    )来传递数据,只要把它作为一个方法参数传递就足够了。你应该尽量避免。它将使代码更容易理解,从而正确编写,等等