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 正在读取不应该存在的数据 的相关文章

  • 使用 C#.net 中的私有存储库的身份验证读取 BitBucket API

    我已经尝试了几天让 BitBucket API 为我工作 但是当涉及到让它为具有身份验证的私有存储库工作时 将问题设置为私有 当它们设置为公开 无需身份验证 一切正常 代码示例如下 static void Main string args
  • 如何从对Web服务发出的请求中获取客户端IP地址

    我的 IIS 中托管有一个 Web 服务 当客户端直接使用我的服务时 我需要找出客户端 IP 地址 like http MyIpAddress MyApplication MyWebServiceClass asmx http MyIpAd
  • 从 unsigned char* 到 char* 的转换无效

    这是一个代码 1 int main int argc char argv 2 3 signed char S psc 4 unsigned char U pusc 5 char C pc 6 7 C S 8 C U 9 10 pc psc
  • ASP.NET 如何在 Web API 中读取多部分表单数据?

    我将多部分表单数据发送到我的 Web API 如下所示 string example my string HttpContent stringContent new StringContent example HttpContent fil
  • 基于多线程的 RabbitMQ 消费者

    我们有一个 Windows 服务 它监听单个 RabbitMQ 队列并处理消息 我们希望扩展相同的 Windows 服务 以便它可以监听 RabbitMQ 的多个队列并处理消息 不确定使用多线程是否可以实现这一点 因为每个线程都必须侦听 阻
  • C++ 中可以使用匿名类作为返回类型吗?

    有没有办法在 C 中使用匿名类作为返回类型 我用谷歌搜索这可能有效 struct Test fun 但是这段代码无法编译 错误信息是 新类型不能在返回类型中定义 其实代码没有任何意义 我只是想弄清楚匿名类是否可以用作C 中的返回类型 这是我
  • 仅针对某些异常类型中断

    我知道异常处理是一件非常重要的事情 我们在所有项目中都在这样做 主要原因是记录客户发生的错误 这工作正常 根本不是问题 但是 当我仍在使用 Visual Studio 编码和运行应用程序时 我根本不需要任何异常处理 我希望调试器正好停在应用
  • 如何修复此 YCrCb -> RBG 转换公式?

    我使用的公式来自这个问题 https stackoverflow com questions 8838481 kcvpixelformattype 420ypcbcr8biplanarfullrange frame to uiimage c
  • 如何从命名空间内重载运算符<<

    这是我能想到的最小的包含示例 首先是类的标题 每当使用 pragma once ifndef EURO H define EURO H include
  • Xcode 新手无法用 C++ 打开文件?

    我一直在我参加的课程中使用 Windows 但我正在尝试运行基本代码来弄清楚如何从 Xcode 上的文件打开 关闭 输入 输出 而我通常在 Visual Studio 上使用的代码不是不知道为什么 谢谢 include
  • 如何使用 Selenium Webdriver .NET 绑定设置 Chrome 首选项?

    这是我正在使用的 用户代理可以成功设置 而下载首选项则不能 Windows 7 Chrome 26 Selenium dotnet 2 31 2 chromedriver win 26 0 1383 0 ChromeOptions chro
  • 使用 C# 的异步 WebRequest

    您好 我有一个函数 它将 url Get 参数传递到网络服务器上的 php 文件 并等待文件的响应 通常需要 10 20 秒 我想将其放入一个循环中 因为我必须一次将这些 Get 请求发送到大约 5 个不同的 php 文件 但是当我尝试将其
  • 在 boost 元组、zip_iterator 等上使用 std::get 和 std::tie

    我有哪些使用选择std get lt gt and std tie lt gt 与增强结构一起 例子 我想使用基于范围的 for 循环在多个容器上进行迭代 我可以实施zip函数 它使用boost zip iterator include
  • 从 cin 读取整数序列并将它们存储在向量中

    这就是我读取整数的方法std cin并将它们存储在向量中 int number vector
  • 我应该害怕使用 UDP 进行客户端/服务器广播通话吗?

    我在过去的两天里阅读了每一篇StackOverflow问题和答案 以及googling当然 关于印地TCP and UDP协议 以便决定在我的用户应用程序和 Windows 服务之间的通信方法中应该使用哪一种 从我目前所看到的来看 UDP是
  • 为什么将未使用的返回值转换为 void?

    int fn void whatever void fn 是否有任何理由将未使用的返回值强制转换为 void 或者我认为这完全是浪费时间 David s answer https stackoverflow com questions 68
  • 如何在RcppParallel中调用用户定义的函数?

    受到文章的启发http gallery rcpp org articles parallel distance matrix http gallery rcpp org articles parallel distance matrix 我
  • 曲线/路径骨架二值图像处理

    我正在尝试开发一个可以处理图像骨架的路径 曲线的代码 我想要一个来自两点之间骨架的点向量 该代码在添加一些点后结束 我没有找到解决方案 include opencv2 highgui highgui hpp include opencv2
  • 查找文本文件中每行的行大小

    如何计算每行中的字符或数字数量 是否有类似 EOF 的东西更像是行尾 您可以遍历行中的每个字符并不断增加计数器直到行尾 n 遇到 确保以文本模式打开文件 r 而不是二进制模式 rb 否则流不会自动将不同平台的行结束序列转换为 n 人物 这是
  • 从 git 签出后 nuget dll 丢失

    I have a C solution containing different projects On those projects I have some normal nuget packages like Newtonsoft Js

随机推荐

  • 路由 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 个块 直到达到