TCP 服务器接收到的数据比预期多

2023-12-04

我有一个服务器客户端应用程序,其中客户端将图像数据流式传输到服务器。我有以下结构:

Client:

private void SerializeAndSendMessage(Message msg) {
        BinaryFormatter formatter = new BinaryFormatter();
        MemoryStream stream = new MemoryStream();
        formatter.Serialize(stream, msg);
        byte[] buffer = stream.ToArray();

        if (clientSocket != null)
        {
            if (clientSocket.Connected)
            {
                clientSocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, SendCallback, null);
            }
        }
    }

private void SendCallback(IAsyncResult ar) {
        try
        {
            clientSocket.EndSend(ar);
            Debug.WriteLine("Message sent.");
        }
        catch (Exception ex)
        {
            //
        }
    }

Server:

  private void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            int received = clientSocket.EndReceive(ar);
            Array.Resize(ref buffer, received);
            BinaryFormatter formatter = new BinaryFormatter();

            MemoryStream stream = new MemoryStream(buffer);

            object obj = null;
            stream.Position = 0;
            try
            {
                obj = formatter.Deserialize(stream);
            }
            catch (Exception ex )
            {
               //
            }

            // processing data

            Array.Resize(ref buffer, clientSocket.ReceiveBufferSize);
            clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, null);
        }
        catch (Exception ex)
        {
            //
        }
    }

我期望发生什么:

  1. 服务器开始接受客户端的数据
  2. 客户端发送大小为X的数据
  3. 服务器接收到大小为X的数据并开始处理它
  4. 同时客户端仍在发送数据
  5. 服务器没有收到此数据
  6. 服务器完成处理接收到的数据,现在开始从客户端接收数据
  7. goto 2

怎么了:

  1. 服务器开始接受客户端的数据
  2. 客户端发送大小为X的数据
  3. 服务器接收到大小为X的数据并开始处理它
  4. 同时客户端仍在发送数据
  5. 服务器没有收到此数据
  6. 服务器完成处理接收到的数据,现在开始从客户端接收数据
  7. 客户端发送第 N 个大小为 X 的数据包
  8. 服务器接收大小为M*X的数据

这显然会导致服务器上的缓冲区填满并且无法反序列化发送的包。我缺少什么?我可以做什么来实现上述工作?


TCP 是一种流式传输协议。如果您在客户端接连执行多个发送操作,TCP 会在尝试填充 MTU 时将它们组合成一个段。

如果 mtu 已满或连续 50ms 计时器过去,或者客户端本身必须确认从服务器收到的数据包,则 TCP 将发送。

TCP是一个非常复杂的协议。其中还有一个计算窗口大小的算法。此外,该窗口大小还会影响客户端接收的数据段的大小。

底线是因为 TCP 是流协议,所以不存在通过套接字接收的数据包的概念。您收到任意数量的字节,您必须根据您正在执行的操作自行将其附加到某种接收缓冲区。如果您需要数据包,那么您必须在发送的数据前面添加长度字段,并在服务器上考虑该长度。这当然会使代码变得复杂。或者,如果您想保持简单,只需使用 UDP。 UDP 确实支持数据包,如果数据包没有在某处丢失,您发送的内容将以相同的大小在接收器处接收。 但UDP不可靠,数据包可能会丢失。 TCP 是可靠的、面向连接的,但比较复杂。

一般来说,套接字编程不是初学者的话题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TCP 服务器接收到的数据比预期多 的相关文章

  • 使用 Unity 在构造函数中使用属性依赖注入

    好的 我在基类中定义了一个依赖属性 我尝试在其派生类的构造函数内部使用它 但这不起作用 该属性显示为 null Unity 在使用 container Resolve 解析实例后解析依赖属性 我的另一种选择是将 IUnityContaine
  • WinSock.h 和 WinSock2.h 使用哪个?

    有谁知道 WinSock h 和 WinSock2 h 之间的区别 我知道它们不使用相同的库 lib 但我不知道 WinSock2 是否仅添加了新功能 或者是否还改进了 WinSock 1 功能 我正在使用 IP TCP 套接字 并希望使用
  • 向 Nhibernate 发出 SQL 查询

    如何将此 SQL 查询发送给 Nhibernate SELECT Customer name FROM Company INNER JOIN Customer ON Company CompanyId Customer CompanyId
  • 在新的浏览器进程中打开 URL

    我需要在新的浏览器进程中打开 URL 当浏览器进程退出时我需要收到通知 我当前使用的代码如下 Process browser new Process browser EnableRaisingEvents true browser Star
  • 存储来自其他程序的事件

    我想将其他应用程序的事件存储在我自己的应用程序中 事件示例 打开 最小化 Word 或打开文件时 这样的事可能吗 运行程序 http msdn microsoft com en us library ms813609 aspx and 打开
  • 生成(非常)大的非重复整数序列而不进行预洗牌

    背景 我编写了一个简单的媒体客户端 服务器 我想生成一个不明显的时间值 随从客户端到服务器的每个命令一起发送 时间戳中将包含相当多的数据 纳秒分辨率 即使它不是真正准确 因为现代操作系统中计时器采样的限制 等 我想做的 在 Linux 上
  • 用于检查项目文件中的项目变量和引用路径的 api

    我正在研究一个 net application VS2010 与 x 没有 解和变量号这些解决方案中的项目数量 我需要检查项目属性 特定于一定数量的项目 是否同质 并且检查 验证构建期间的参考路径 有没有一个API是这样的吗 如果没有 我该
  • 获取 WPF 控件的所有附加事件处理程序

    我正在开发一个应用程序 在其中动态分配按钮的事件 现在的问题是 我希望获取按钮单击事件的所有事件 因为我希望删除以前的处理程序 我尝试将事件处理程序设置为 null 如下所示 Button Click null 但是我收到了一个无法分配 n
  • 使用 JNI 从 Java 代码中检索 String 值的内存泄漏

    我使用 GetStringUTFChars 从使用 JNI 的 java 代码中检索字符串的值 并使用 ReleaseStringUTFChars 释放该字符串 当代码在 JRE 1 4 上运行时 不会出现内存泄漏 但如果相同的代码在 JR
  • 未经许可更改内存值

    我有一个二维数组 当我第一次打印数组的数据时 日期打印正确 但其他时候 array last i 的数据从 i 0 到 last 1 显然是一个逻辑错误 但我不明白原因 因为我复制并粘贴了 for 语句 那么 C 更改数据吗 I use g
  • 如何将整数转换为 void 指针?

    在 C 中使用线程时 我面临警告 警告 从不同大小的整数转换为指针 代码如下 include
  • Visual Studio 中的测试单独成功,但一组失败

    当我在 Visual Studio 中单独运行测试时 它们都顺利通过 然而 当我同时运行所有这些时 有些通过 有些失败 我尝试在每个测试方法之间暂停 1 秒 但没有成功 有任何想法吗 在此先感谢您的帮助 你们可能有一些共享数据 检查正在使用
  • 如何使用 Mongodb C# 驱动程序连接多个集合

    我需要将 3 个集合与多个集合合并在一起 lookup我在 C 驱动程序中尝试过 它允许我 lookup用户采集但无法执行秒 lookup用于设置集合 有人可以帮忙吗 db Transactions aggregate lookup fro
  • 等待线程完成

    private void button1 Click object sender EventArgs e for int i 0 i lt 15 i Thread nova new Thread Method nova Start list
  • (de)从 CSV 序列化为对象(或者最好是类型对象的列表)

    我是一名 C 程序员 试图学习 C 似乎有一些内置的对象序列化 但我在这里有点不知所措 我被要求将测试数据从 CSV 文件加载到对象集合中 CSV 比 xml 更受青睐 因为它更简单且更易于人类阅读 我们正在创建测试数据来运行单元测试 该集
  • 为什么在setsid()之前fork()

    Why fork before setsid 守护进程 基本上 如果我想将一个进程与其控制终端分离并使其成为进程组领导者 我使用setsid 之前没有分叉就这样做是行不通的 Why 首先 setsid 将使您的进程成为进程组的领导者 但它也
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 编译时“strlen()”有效吗?

    有时需要将字符串的长度与常量进行比较 例如 if line length gt 2 Do something 但我试图避免在代码中使用 魔法 常量 通常我使用这样的代码 if line length gt strlen Do somethi
  • 线程和 fork()。我该如何处理呢? [复制]

    这个问题在这里已经有答案了 可能的重复 多线程程序中的fork https stackoverflow com questions 1235516 fork in multi threaded program 如果我有一个使用 fork 的
  • 如何使用 Word Automation 获取页面范围

    如何使用办公自动化找到 Microsoft Word 中第 n 页的范围 似乎没有 getPageRange n 函数 并且不清楚它们是如何划分的 这就是您从 VBA 执行此操作的方法 转换为 Matlab COM 调用应该相当简单 Pub

随机推荐

  • PHP 和 MySQL 错误:类 mysqli_result 的对象无法转换为字符串 [重复]

    这个问题在这里已经有答案了 我收到错误 mysqli result 类的对象无法转换为字符串 Code
  • 强命名会导致 C# 中的对象序列化出现问题吗?

    我序列化一些配置对象并将结果字节存储在数据库中 new BinaryFormatter Serialize memoryStream instance Convert ToBase64String memoryStream ToArray
  • 像 facebook 一样从 Javascript 更改 URL

    我目前正在开发一个面向 AJAX 的 Web 应用程序 我一直在寻找使用浏览器 URL 复制当前 AJAX 状态 或应用程序状态 的不同方法 因此刷新和后退按钮也可以工作 在过去的几周里 我看到了涉及使用哈希 和不同 JS 框架的不同方法
  • 如何在现有表单中显示 FSharp.Charting 图表?

    我不明白如何创建图表控件并将图表放置在现有表单中 我在网上找到的所有示例都以新表单显示图表 但我想将图表添加到我现有的表单之一 我在想这样的事情 let form new Form Text My form let lbl new Labe
  • R 函数识别不匹配的行

    我正在尝试比较 2 个 data frames V1 代表我的 CRM V2 代表我想要发送的潜在客户 V1 大约有 8k 个元素 V2 大约有 25k 个元素 我需要将 V2 中的每一行与 V1 中的每一行进行比较 丢弃 V1 中存在 V
  • 如何在.Net Framework中将方法注入到自动属性中

    我有一些具有许多属性的 Foo 类 public class Foo public int Property1 get set public int Property2 get set public int Property3 get se
  • 在 Redshift 中拆分行

    在我的表中 数据如下 col1 col2 col3 col4 A1 A2 A3 4 B1 B2 B3 3 C1 C2 C3 1 我需要如下输出 col1 col2 col3 col4 A1 A2 A3 1 A1 A2 A3 2 A1 A2
  • 如何在更多线程上运行 boost asio 解析器服务?

    我在 SNMPV2 实现中使用 boost asio ip udp resolver 来确定主机是否可达 using Resolver boost asio ip udp resolver Resolver resolver ioServi
  • 如何在 Perl 源代码中嵌入中文字符?

    在我的脚本中 我需要将一些汉字 qw 到字符串中 当我运行脚本时 perl 指出脚本中存在无法识别的字符 虽然我知道它一定与编码相关的东西有关 但我不知道如何解决它 所以向你寻求帮助 提前致谢 在 Perl 源代码中嵌入文字字符串很容易 使
  • 如何防止应用程序在完成任务之前关闭?

    我用 C 制作了一个 Windows 控制台应用程序 可以进行一些计算 应用程序窗口对用户来说是不可见的 应用程序作为任务运行 这些计算结果保存到数据库中 不幸的是 如果用户在保存数据期间关闭此应用程序 通过关闭计算机 并且并非所有数据都会
  • 使用 Spark 并行缓存和查询数据集

    我有一个要求 我想缓存一个数据集 然后通过在该数据集上并行触发 N 个查询来计算一些指标 并且所有这些查询都会计算类似的指标 只是过滤器会发生变化 并且我想在其中运行这些查询并行 因为响应时间至关重要 并且我想要缓存的数据集大小始终小于 G
  • 如何创建 100M 字节缓冲区

    我正在测试 Linux 上接口的吞吐量 我正在使用 DMA 进行数据传输 DMA 需要连续的内存位置 但 kmalloc 无法分配超过 1MB 的空间 有没有其他方法可以创建高达 100M 字节的大缓冲区位置 我认为 kmalloc 无法分
  • IBM Worklight 6.0.0.1 - 推送通知轮询在生产环境中不起作用

    我的问题是这样的 When in 开发环境 一切正常 轮询器工作正常 数据库状态发生变化等 When in 生产环境 日志中没有出现任何内容 数据库中也没有任何变化 我正在从数据库表中读取通知 推送通知事件来源 WL Server crea
  • 来自数据库结果的 PHP 多维数组

    我对多维数组有点陌生 想看看我做得是否正确 最好 我想在主数组中命名数组以便于使用 unique array array username gt array user id gt array weeknumber gt array 然后我有
  • 使用 jquery 突出显示选定的文本

    当用户选择 html 页面中的任何文本时 我想添加自定义样式 例如color red 到它 这将充当突出显示工具 类似于您在某些用于阅读 pdf 文件的应用程序中看到的工具 为此我声明highlight 获取所选文本及其位置的函数 func
  • 如何以如下形式创建对象:ifstream in();

    我是 C 初学者 我见过好几次创建对象时 如下所示 class name object name 之后 您可以将 object name 引用为该类的对象 我怎样才能在课堂上做到这一点 我应该重写构造函数吗 以及如何做到这一点 这行代码可能
  • 在模型挂钩后设置控制器属性

    我需要在之后设置一个控制器属性model钩 我可以想到两种方法来做到这一点 model params return this store findRecord user 1 afterModel model transition model
  • Eclipse Maven Spring:当我尝试作为服务器运行时出现服务器错误 (Tomcat 7)

    我有一个 Java 项目 使用春季MVC框架和Maven作为其构建系统 我希望使用的主要 IDE 是用于 Java EE 的 Eclipse 我的应用程序使用标准 Maven 项目结构 源代码位于src main java 应用程序的资源位
  • 将 JSON 发布到 MVC 控制器 - 字符串参数为 null

    我故意尝试不在控制器参数中使用绑定 因此我有一个如下所示的控制器 HttpPost public ActionResult UntypedForm String serializedformdata 当我使用以下代码将序列化的 JSON 表
  • TCP 服务器接收到的数据比预期多

    我有一个服务器客户端应用程序 其中客户端将图像数据流式传输到服务器 我有以下结构 Client private void SerializeAndSendMessage Message msg BinaryFormatter formatt