从TcpClient流中读取所有数据

时间:2013-11-22 16:48:23

标签: c# stream tcpclient

我正在制作一台通过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();
    }

0 个答案:

没有答案