RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1176126
Accepted
Andrei Khotko
Andrei Khotko
Asked:2020-09-09 16:31:14 +0000 UTC2020-09-09 16:31:14 +0000 UTC 2020-09-09 16:31:14 +0000 UTC

.NET 中的 TCP 协议保证

  • 772

有一个问题困扰着我。有一个 GPS 跟踪器,它使用自己的协议通过 TCP / IP 传输数据。我正在编写一个后台服务(.NET Core 3.1),它应该侦听 tcp 端口并将消息包以原始形式(字节 [] 或编码为字符串)保存到数据库中。现在我的 tcp 端口嗅探代码如下所示:

public class TcpListenerBackgroundService : BackgroundService
{
    private readonly ITcpListenerWrapper _tcpListener;
    private readonly ILogger<TcpListenerBackgroundService> _logger;

    public TcpListenerBackgroundService(ITcpListenerWrapper tcpListener, ILogger<TcpListenerBackgroundService> logger)
    {
        _tcpListener = tcpListener;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await _tcpListener.StartListeningAsync(stoppingToken);
    }
}

TcpListenerWrapper.cs

public sealed class TcpListenerWrapper : ITcpListenerWrapper, IDisposable
{
    private const int BufferSize = 1024;

    private readonly TcpListener _listener;
    private readonly IMessageManager _messageManager;

    public TcpListenerWrapper(ITcpListenerWrapperConfiguration config, IMessageManager messageManager)
    {
        _listener = new TcpListener(IPAddress.Any, config.PortNumber);
        _messageManager = messageManager;
    }

    public async Task StartListeningAsync(CancellationToken stoppingToken)
    {
        _listener.Start();

        while (!stoppingToken.IsCancellationRequested)
        {
            var client = await _listener.AcceptTcpClientAsync();
            var stream = client.GetStream();

            while (!stoppingToken.IsCancellationRequested)
            {
                var buffer = new byte[BufferSize];

                using (var ms = new MemoryStream())
                {
                    int numBytesRead;
                    while ((numBytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        ms.Write(buffer, 0, numBytesRead);
                    }

                    if (ms.Length > 0)
                    {
                        var messageAsText = Encoding.ASCII.GetString(buffer);
                        // Console.WriteLine($"New message received: {messageAsText}");

                        var message = _messageManager.CreateMessage(buffer);
                        message.Save(); // Сохранение в бд.
                    }
                }
            }
        }
    }

    public void Dispose()
    {
        _listener.Stop();
    }
}

让 GPS 追踪器以 1 分钟的周期发送 10 个数据包。

问题:是否有可能NetworkStream一次有多个包(比如 3 个包)?或者有保证他们会一次来一个吗?

添加。问题:消息监听代码是否有错误?也许这里缺少一些东西,或者反之亦然,太多了?

c#
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    KoVadim
    2020-09-09T16:42:42Z2020-09-09T16:42:42Z

    问题:是否有可能同时在 NetworkStream 中有多个数据包(例如 3 个数据包)?或者有保证他们会一次来一个吗?

    .NET 不知道(也不应该)某种 GPS 跟踪器正在那里传输数据。随着字节的到来,它们将被添加。也就是说,理论上,可以先来两个半包,然后再来一个半包。也许以另一种方式。TCP 以字节为单位运行。并且该协议仅保证字节(字节!)将以相同的顺序到达,不会出现“意外丢失的字节/位”。此外,协议将尝试传递数据包,或者如果无法传递(线路被切断),将“断开连接”。

    看了看代码。您正在尝试将每个传入数据包解码为完全传入的数据包。但只有这一点是有保证的。是的,通过本地测试,它很可能通常以这种方式工作。但是,一旦 Windows 决定气馁(防病毒程序已启动)或路由器 / gsm 模块后面的网络。它可以是任何东西。

    我有一个案例,由于一个众所周知的防火墙,第一次读取总是第一个字节。然后一切照常。但他并没有一直这样做。代码中的程序员期望立即需要至少 4 个字节。和不...

    在代码中做什么。在这个协议中,消息分隔符很可能是换行符。因此,数据来了,添加到缓冲区的末尾,然后寻找换行符。是的 - 提取包,重复搜索。否 - 直到下一个包裹。

    • 3

相关问题

  • 使用嵌套类导出 xml 文件

  • 分层数据模板 [WPF]

  • 如何在 WPF 中为 ListView 手动创建列?

  • 在 2D 空间中,Collider 2D 挂在玩家身上,它对敌人的重量相同,我需要它这样当它们碰撞时,它们不会飞向不同的方向。统一

  • 如何在 c# 中使用 python 神经网络来创建语音合成?

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5