我在通过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;
}
}
}
}
答案 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
属性值StringBuilder
,而在这里你甚至不会迭代连接!) 当然,并非所有这些缺陷都是致命的。最大的问题是每次读取时新的NetworkStream
以及接收缓冲区和结果值的管理不善。但实际上,你应该努力使所有的代码变得更好。
请注意,上述内容仅改进了代码。即使上面的内容仍然存在“我在任何上下文中看到的最常见的新手错误”的变化:虽然它确实使用了读取操作的返回值,但它并没有完成它应该做的所有事情。特别是:
Socket.Shutdown(SocketShutdown.Both)
并最后调用Socket.Close()
。但上述内容至少可以帮助您在项目中取得进展。
你真的应该改变另外一件事,我在上面没有打扰,是你不应该使用实例字段(即readData
)来传递数据,只需将其作为方法参数传递即可满足。您应该尽可能避免side-effects in your code。它将使代码更容易理解,从而正确地编写,等等。