我正在制作一台通过PC控制的新机器。电流卡在与通过以太网连接的摄像机系统进行通信时。
这是我打开连接的代码。
TcpClient client;
NetworkStream stream;
public bool OpenConnection()
{
client = new TcpClient();
try
{
//Camera.Open();
client.Connect("192.168.0.10", 8500);
stream = client.GetStream();
}
catch (Exception ex)
{
return false;
}
return true;
}
到目前为止一切顺利。连接打开后,我会从摄像头请求一些信息 我使用的消息格式有STX(0x02)表示消息的开头,ETX(0x03)表示消息的结尾。
char StartOfPacket = (char)0x02;
char EndOfPacket= (char)0x03;
public bool RetrieveDigits(out string Digits)
{
// Send the trigger cammand to the vision system
Digits = "";
bool EverythingOK = true;
string DataToSend = StartOfPacket + "T1" + EndOfPacket;
byte[] buff = Encoding.ASCII.GetBytes(DataToSend);
if (LogCameraEvent != null)
LogCameraEvent(">> " + DataToSend);
try
{
stream.Write(buff, 0, buff.Length);
}
catch (Exception ex)
{
Logging.Instance.LogExceptionToFile(MethodBase.GetCurrentMethod(), ex);
EverythingOK = false;
}
Thread.Sleep(100);
byte[] buffer;
if (EverythingOK)
{
// Check the response
buffer = ReadCamera(10);
// Process the packets
string[] packets = ProcessPackets(buffer);
if (packets != null)
{
if (packets.Length > 0)
{
bool TriggerFound = false;
for (int i = 0; i < packets.Length; i++)
{
if (packets[i] == "T1")
{
TriggerFound = true;
continue;
}
else if (TriggerFound)
{
// If we are here then we should now be the data that was requested
if (string.IsNullOrEmpty(packets[i]))
{
Digits = packets[i-1]; // previous packet may have data from previous trigger. Need to look into why this happens.
}
else
Digits = packets[i];
EverythingOK = true;
break;
}
else
EverythingOK = false;
}
}
else
{
Console.WriteLine("No Packets Recieved");
EverythingOK = false;
}
}
else
{
Console.WriteLine("No Packets Recieved");
EverythingOK = false;
}
}
return EverythingOK;
}
以下是我认为问题所在的部分,即获得回复。
private byte[] ReadCamera(int ExpectedLength)
{
if(ExpectedLength < 1)
{
ExpectedLength = 100;
}
byte[] Buffer = new byte[ExpectedLength];
int read = 0;
int chunk;
while(stream.DataAvailable)
{
chunk = stream.Read(Buffer, read, Buffer.Length-read);
read += chunk;
// If we have reached the end of our buffer, check to see if theres any more information
if(read == Buffer.Length)
{
if(!stream.DataAvailable)
return Buffer;
// Nope. Resize the buffer, put the byte we've just read and continue
byte[] newBuffer = new byte[Buffer.Length * 2];
Array.Copy(Buffer, newBuffer, Buffer.Length);
Buffer = newBuffer;
//read++;
}
else if(!stream.DataAvailable)
return Buffer;
Thread.Sleep(50);
}
// Buffer is now too big, shrink it
byte[] ret = new byte[read];
Array.Copy(Buffer, ret, read);
return ret;
}
private string[] ProcessPackets(byte[] data)
{
// look for the stat char
List<string> Packets = new List<string>();
byte Start = 0x02;
bool StartFound = false;
byte End = 0x03;
StringBuilder sb = new StringBuilder();
for(int i =0; i<data.Length; i++)
{
if(StartFound)
{
// Check to see if its the end
if (data[i] == End)
{
Packets.Add(sb.ToString());
sb.Clear();
}
else
sb.Append(Encoding.ASCII.GetChars(data, i, 1));
}
// Find the start
if (!StartFound)
{
if (data[i] == Start)
{
StartFound = true;
}
}
}
return Packets.ToArray();
}
让我解释一下应该发生什么,然后解释发生了什么。通过RetrieveDigits
方法我将“T1”发送到相机。相机将做的是回复“T1”,然后是2个ascii字符,现在我们将说AA。使用相机系统上的诊断应用程序,我可以监控以太网,我看到以下内容。
(&gt;&gt;表示由相机收到) (&lt;&lt;表示从相机发送)
>>[STX]T1[ETX]
<<[STX]T1[ETX][STX]AA[ETX]
所以我看到了相机发送的内容。我确认PC已经使用线鲨收到了数据。
现在进一步在RetrieveDigits
方法中你可以看到我处理收到的数据包,循环通过数据包,直到我找到“T1”,然后假设下一个数据包将是我所追求的数据并设置{{1}这个值。
我发现有时当我运行应用程序时,我发现Digits
设置为“”。
我也发现有时收到的数据是“AA”然后是“T1”而不是“T1”然后是“AA”。我怀疑发生的事情是,当它回到前面时,“AA”实际上来自相机发送的先前数据,并且出于某种原因,从流中读取时它被遗漏了。
在Stream.Available为false之前,我正在读取数据时,不知道为什么会发生这种情况。
编辑:
修改了Digits
代码来处理数据包,一次读取1个字节。
ReadCamera
并修改调用这样的方法
private string[] ReadCamera(int ExpectedLength, int ExpectedPackets)
{
List<string> Packets = new List<string>();
bool StartFound = false;
StringBuilder sb = new StringBuilder();
if(ExpectedLength < 1)
{
ExpectedLength = 100;
}
byte[] Buffer = new byte[ExpectedLength];
int read = 0;
while (true)
{
read += stream.Read(Buffer, read, 1);
// Check to see if the byte read is the start of a packet
if (Buffer[read - 1] == StartOfPacket)
{
StartFound = true;
}
else if (StartFound)
{
// Check to see if the byte read is the end of a packet
if (Buffer[read - 1] == EndOfPacket)
{
Packets.Add(sb.ToString());
sb.Clear();
StartFound = false;
if (Packets.Count == ExpectedPackets)
break;
}
else
{
sb.Append(Encoding.ASCII.GetChars(Buffer, read - 1, 1));
}
}
}
// For Debuggin purposes
foreach(string s in Packets)
if (LogCameraEvent != null)
LogCameraEvent("<< " + s);
return Packets.ToArray();
}