C#-从TCP连接读取数据时,某些数据包被丢弃

C#-从TCP连接读取数据时,某些数据包被丢弃,c#,.net,sockets,tcp,C#,.net,Sockets,Tcp,我使用C#读取TCP连接上的连续数据流(瘙痒数据,即外汇价格),但在运行应用程序较长时间后,有时应用程序会丢弃数据包,信息丢失 下面是我用来读取数据的代码片段: private void ReaderThreadStarter() { StreamReader streamReader = new StreamReader(this._networkStream); while (!_stopping) { try

我使用C#读取TCP连接上的连续数据流(瘙痒数据,即外汇价格),但在运行应用程序较长时间后,有时应用程序会丢弃数据包,信息丢失

下面是我用来读取数据的代码片段:

private void ReaderThreadStarter()
    {
        StreamReader streamReader = new StreamReader(this._networkStream);
        while (!_stopping)
        {
            try
            {
                if (this._networkStream.DataAvailable)
                {
                    while ((line = streamReader.ReadLine()) != null)
                    {
                        lock (_queue.ConcurrentQueue)
                        {
                            byte[] data = System.Text.Encoding.ASCII.GetBytes(line);
                            Log.Info("Data Added in Queue: " + Encoding.ASCII.GetString(data, 0, data.Length));
                            _queue.WriteToQueue(data);
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                Log.Error(exception);
            }
            finally
            {
                SetStopped();
            }
        }
    }
上面这段代码的作用是从TCP连接读取数据并将其写入并发队列,然后另一个线程使用队列中的数据进行处理。所以基本上是一个简单的生产者-消费者问题

生产者-消费者部分似乎工作正常,因为我在队列中写的内容被消费者使用

一种选择是使用嗅探器并确认应用程序正在丢弃数据包,但我在一个无法使用嗅探器的环境中工作。我之所以相信会有数据包丢失,是因为我的一些外汇订单从未被取消,我的价格下跌,而数据提供商告诉我,最后的价格是正确的

我还记录了在保存到队列中之前从TCP端口读取的数据,因此从日志中我假设数据在从连接读取时丢失

有人能告诉我我在这里可能做错了什么,或者丢弃数据包的原因是什么吗

以下是我的消费者代码的代码片段:

public void ReadQueue()
    {
        try
        {
            while (true)
            {
                {
                    byte[] data = _queue.ReadFromQueue();

                    Parse(data);
                }
            }
        }
        catch (Exception exception)
        {
            Log.Error(exception);
        }
    }

public byte[] ReadFromQueue()
    {
        try
        {
            byte[] data;
            lock (this) // Enter synchronization block
            {
                ConcurrentQueue.TryDequeue(out data);
            } 
            return data;
        }
        catch (Exception exception)
        {
            Log.Error(exception);
            return null;
        }
    }

有两件事吸引了我的眼球;首先是使用
DataAvailable
。使用此功能几乎从来都不是正确的做法。这对于在同步和异步方法之间进行选择非常有用。例如,它确实告诉您是否有更多的数据入站,并且可能会给出“假阳性”(因为您正在使用它并不意味着什么的东西),从而导致循环过早退出
DataAvailable
只告诉您本地缓冲区中当前是否有可用的数据,这就是它告诉您的全部内容

我感兴趣的第二件事是
数据是二进制还是文本。您使用的是
StreamReader
提示文本,但是。。。为什么要将其重新编码回
字节[]
?如果它是任意二进制文件,则不能将其作为文本处理-这将不起作用。当您通过
StreamReader
获取它时,您已经损坏了内容。如果是基于文本的协议,不要对其重新编码:使用字符串队列(或类似队列)


另一方面。。。如果队列是真正并发的,您可能不需要同步访问。

TCP 100%确保您不会丢失数据包。错误在代码中。数据包丢失不是问题。为什么要读取字符串,然后将其转换为字节?这就是全部代码吗?在断开连接的情况下,是否有重新连接机制?正如上面usr所说,在TCP的情况下,数据丢失是不可能的。@usr-我正在将其转换为字节,因为我从数据提供程序获得了一个字节格式,指明了在哪个位置有什么信息。@Lior Ohana-我有一个重新连接机制,如果连接丢失并重新连接,它将被记录。所以没有连接丢失。@Marc Gravell-我做了一些改变,记住了你提到的要点。还可以使用嗅探器查看我的应用程序是否跳过数据包。事实证明,我认为我的应用程序丢弃的消息也没有在嗅探器日志中找到,因此可以安全地假设这些消息从未由数据提供者生成吗?@Taimoor如果它们没有发送,它们就没有被发送。您没有显示消费者代码,因此我无法对制作人做出任何有根据的评论。@Marc Gravell-事实上,我只是将嗅探日志文件与我的应用程序制作人日志(上面的代码)进行了比较。@Marc Gravell-我还将我的消费者代码片段添加到主帖子中。@TaimoorChoudhary我指的是TCP源代码