NetworkStream 正在读取不应该存在的数据

2024-03-09

我在 NetworkStream 从套接字缓冲区读取不应该存在的数据时遇到问题。顺便说一句,我正在发送非常大的缓冲区。现在我刚刚在本地主机上进行测试。

这是我读取数据的方式,前 4 个字节包含消息的长度,然后我只读取 4096 个块,直到达到消息的长度。

    protected TcpClient tcpObject;
    protected NetworkStream tcpStream;

    private void HandleComm()
    {
        try
        {
            tcpStream = tcpObject.GetStream();
            byte[] totalByteAray = new byte[constIntSize];
            byte[] message = new byte[constChunkSize];
            byte[] fullMessage = new byte[0];

            //this is how many bytes long the message will be
            int totalBytes = 0;
            int currentBytes = 0;
            int chunkSize = constChunkSize;

            while (true)
            {
                //skip reading if no data is available
                //DataAvailable does not tell you when all the data has arrived
                //it just tell you if some data has arrived
                if (tcpStream.CanRead)
                {
                    totalBytes = 0;
                    currentBytes = 0;
                    message = new byte[constChunkSize];
                    chunkSize = constChunkSize;

                    //The first 4 bytes of the message will always contain the length of the message, not including
                    //the first 4 bytes. This is how you know when to stop reading.
                    tcpStream.Read(totalByteAray, 0, constIntSize);                        
                    //there are 4 bytes in a 32 bit number, so totalByteArrayContains 4 index that is a byte which is
                    //the 32 bit int that tells us how many bytes the whole message will be.
                    //now convert the totalByteArray to a 32bit int
                    totalBytes = BitConverter.ToInt32(totalByteAray, 0);
                    Console.WriteLine("reading " + totalBytes);
                    //fullMessage will contain the entire message but it has to be built message by message.                    
                    fullMessage = new byte[totalBytes];
                    //keep reading until we get all the data
                    while (currentBytes < totalBytes)
                    {

                        //when you send something over TCP it will some times get split up
                        //this is why you only read in chuncks, 4096 is a safe amount of bytes
                        //to split the data into.
                        if (totalBytes - currentBytes < constChunkSize)
                        {
                            chunkSize = totalBytes - currentBytes;
                            message = new byte[chunkSize];
                        }

                        tcpStream.Read(message, 0, chunkSize);
                        //since we know each chunk will always come in at 4096 bytes if it doesn't that means that it's the end
                        //this part cuts off the extra empty bytes                           

                        //copy the message to fullMessage starting at current bytes and ending with the bytes left
                        message.CopyTo(fullMessage, currentBytes);
                        currentBytes += chunkSize;                            
                    }

                    //message has successfully been received
                    if (totalBytes != 0)
                    {

                        if (OnRawDataReceived != null)
                        {
                            RawDataReceivedArgs args = new RawDataReceivedArgs();
                            args.Data = new byte[fullMessage.Length];
                            fullMessage.CopyTo(args.Data, 0);
                            OnRawDataReceived(this, args);
                        }

                        totalBytes = 0;
                    }
                }
            }
        }
        catch
        {
            connectionStatus = ConnectionStatus.NotConnected;
            if (OnDisConnect != null)
                OnDisConnect(this, null);
        }
    }

这是我发送数据的方式,我只是获取消息的长度,然后创建一条新消息,其中前 4 个字节是消息的长度,其余的是实际消息。

    protected void sendData(byte[] data)
    {
        //we need to know how big the data that we are sending will be
        int length = data.Length;
        System.Console.WriteLine("writing " + length);
        //convert the 32bit int to a 4 byte array
        byte[] lengthArray = BitConverter.GetBytes(length);

        //init the main byte array that will be sent over
        byte[] buffer = new byte[length + constIntSize];

        //the first 4 bytes will contain the length of the data
        lengthArray.CopyTo(buffer, 0);

        //the rest of the buffer will contain the data being sent
        data.CopyTo(buffer, constIntSize);

        //wite it to the client stream
        tcpStream.Write(buffer, 0, length + constIntSize);
        //now send it
        tcpStream.Flush();           
    }

由于某种原因,我正在读取不应该在缓冲区上的数据。这是控制台输出。

服务器-------------客户端

写作 1024 -> 阅读 1024

读取 1228800

写作 1024 -> 阅读 1024

读取 1228800

阅读7224842

因此,当我单击按钮时,它会发送一个请求,表示我想要来自网络摄像头的图像,该请求是 1024 字节。客户端读取它并发送 1228800 字节的图像。我第一次这样做时,它总是有效。我第二次单击它时,客户端发回了 1228800 字节,服务器读取了正确的字节数,然后在套接字缓冲区应该为空时发现了更多字节要读取。我的套接字缓冲区中没有 7224842 字节,这正是读取的前 4 个字节所说的。

关于为什么缓冲区会在其中获取额外数据的任何想法吗?当我发送较小的消息时,一切似乎都运行良好,但这让我发疯。


tcpStream.Read(totalByteAray, 0, constIntSize);
...
tcpStream.Read(message, 0, chunkSize);

整个问题就在这里。它是一个要求您检查返回到此。不能保证(对于基于网络的 IO,不太可能)您将立即获得整个缓冲区 - 数据包按时传入,API 将为您提供它可以做什么。相反,您将得到“一些”(结果 > 0 且

如果你想阅读exactly这么多数据,然后编写一个实用方法:

static void ReadExact(Stream stream, byte[] buffer, int offset, int count)
{
    int read;
    while(count > 0 && (read = stream.Read(buffer, offset, count)) > 0) {
        offset += read;
        count -= read;
    }
    if(count != 0) throw new EndOfStreamException();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NetworkStream 正在读取不应该存在的数据 的相关文章

  • ROWNUM 的 OracleType 是什么

    我试图参数化所有现有的 sql 但以下代码给了我一个问题 command CommandText String Format SELECT FROM 0 WHERE ROWNUM lt maxRecords command CommandT
  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • C++:无法使用scoped_allocator_adaptor传播polymorphic_allocator

    我有一个vector
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz

随机推荐

  • 路由 iPhone 音频声音

    我有一个可以同时收听和播放声音的应用程序 默认情况下 声音通过耳机输出 因此 我使用以下代码将其路由到扬声器 UInt32 audioRouteOverride kAudioSessionOverrideAudioRoute Speaker
  • 阻止来自我的网站的 cURL 请求

    我有一个网站 其中包含大量产品和价格数据库 我经常被价格困扰 我想用一个来防止它
  • 如何迭代对象中所有唯一的条目对?

    我目前有一个数组数据结构 我像这样迭代 调用foo在每对独特的元素上 for var i 0 i lt arr length i for var j i 1 j lt arr length j foo arr i arr j 但是 我意识到
  • 隐藏输入字段中的“最后一次通过”图标

    如果您在 Chrome 中安装了 Last Pass 扩展 它会显示 在某些输入字段的右侧 我想知道 有没有办法用CSS隐藏它 您还可以通过将此属性添加到输入元素来隐藏图标 data lpignore true
  • 如何正确重写 Spring 和 Hibernate 的 BasicDataSource

    目前我在Spring中有以下基本数据源
  • 将 Pandas Dataframe 导出为 CSV

    这是一个关于如何允许用户在 Python 3 中将 Pandas 数据框导出为 CSV 格式的问题 对于上下文 我有一个 Djangoview接受来自 jQuery 的 POST 请求 这样当用户单击我网站上的按钮时 就会触发对该 Djan
  • 我可以在集合更改事件时回滚集合更改吗?

    我有 2 个列表视图 并在它们之间添加 删除按钮 在视图模型中列表视图集合的集合更改事件中 我可以回滚特定条件的更改吗 你可以处理CollectionChanged http msdn microsoft com en us library
  • 使用 XSLT 创建 JSON 输出单引号转换(XML 到 JSON)

    当我将输入 XML 文件转换为 JSON 输出时 单引号属性将转换为双引号 请任何人指导我解决上述问题 我的输入 XML 文件是
  • Visual Studio 智能感知类建议

    是否可以让 Visual Studio 列出所有类 而不仅仅是导入的命名空间中的类 我知道这种自动导入类型的唯一方法是完全正确地输入类名 然后右键单击并导入 类似于 Eclipse 它可以在您键入时列出所有可用的类 正如这里提到的 Inte
  • iPhone 写入/读取 plist 文件

    我的 iPhone 应用程序中有 plist 我想从我的 single 中读取和写入一个整数并形成它 我有这个来阅读 scoreData score scoreData sharedData filePath stats plist NSM
  • 为什么 BufferedStream.Write 会抛出“此流不支持查找操作”?

    这个让我很困惑 当我什至没有调用它时 我收到有关搜索的错误 我的代码看起来像这样 send 42 uint value 42 byte msg BitConverter GetBytes value stream Write msg 0 s
  • 安装的glimpse尝试访问glimpse.axd并收到404错误?

    这很简单 我在这个页面安装了glimpse http getglimpse com About QuickStart http getglimpse com About QuickStart 然后我尝试导航到http myApp glimp
  • 在 Hibernate 中映射多级继承

    目前我有这样的结构 A B C 它使用连接表与每个子类映射一个表 由于历史原因我也使用了判别器 所以目前的情况如下所述Hibernate 手册第 9 1 3 节 http www hibernate org hib docs v3 refe
  • Mvc ActionLink 与 JavaScript

    我正在使用 MVC 我有一个带有 ActionLink 的视图 它调用我的控制器的 Action 我的问题是当我想在该操作链接的 onClick 事件上调用 javascript 函数时 因为该操作链接转换为执行时间上的 html 标准标记
  • Chrome -> 检查元素 -> 网络 (XHR) -> 预览选项卡 (HTML) 问题

    我在网络部分的预览选项卡上遇到问题 返回 HTML 时 我在预览和响应中看到原始 HTML 有时 但极少数情况下 HTML 会在 预览 选项卡中正确呈现 是我做错了什么还是只是 Chrome 的一些错误 Thanks 我也在测试这个 对我来
  • 如何找到AVPlayer当前比特率

    我正在尝试获取 AVPlayer 播放视频流的比特率 我尝试过observed bit rate的财产AVPlayerItemAccessLogEvent 但它具有非常高的价值 经过进一步探索Observed bit rate财产 我了解该
  • 如何将 OpenCV Mat 划分为矩形子区域?

    我想划分一个简单的Mat 200x200 位于不同区域 10x10 我做了两个循环 然后创建了一个Rect我在其中指出每次迭代中我想要的变量 x y width height 最后 我将图像的该区域保存在vector of Mats 但我的
  • 如何每天自动备份Firestore数据库

    我想每天备份 Firestore 数据库 我的数据结构是这样的 usersCollection uid defaultCurrency USD name something dreamsCollection name image 我看过fi
  • 压倒一切!重要的风格

    标题几乎概括了这一点 外部样式表有以下代码 td EvenRow a display none important 我尝试过使用 element style display inline and element style display
  • NetworkStream 正在读取不应该存在的数据

    我在 NetworkStream 从套接字缓冲区读取不应该存在的数据时遇到问题 顺便说一句 我正在发送非常大的缓冲区 现在我刚刚在本地主机上进行测试 这是我读取数据的方式 前 4 个字节包含消息的长度 然后我只读取 4096 个块 直到达到