c# TCP通信编程

2023-05-16

目录

  • 协议类
    • JSON协议类
    • XML协议类
  • 通信信息适配

协议类

   public abstract class Protocol<TMessageType>
    {
        const int HEADER_SIZE = 4;

        public async Task<TMessageType> ReceiveAsync(NetworkStream networkStream)
        {
            var bodyLength = await ReadHeader(networkStream);
            AssertValidMessageLength(bodyLength);
            return await ReadBody(networkStream, bodyLength);
        }

        public async Task SendAsync<T>(NetworkStream networkStream, T message)
        {
            var (header, body) = Encode(message);
            await networkStream.WriteAsync(header, 0, header.Length);
            await networkStream.WriteAsync(body, 0, body.Length);
        }

        async Task<int> ReadHeader(NetworkStream networkStream)
        {
            var headerBytes = await ReadAsync(networkStream, HEADER_SIZE);
            return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(headerBytes, 0));
        }

        async Task<TMessageType> ReadBody(NetworkStream networkStream, int bodyLength)
        {
            var bodyBytes = await ReadAsync(networkStream, bodyLength);
            return Decode(bodyBytes);
        }

        async Task<byte[]> ReadAsync(NetworkStream networkStream, int bytesToRead)
        {
            var buffer = new byte[bytesToRead];
            int bytesRead = 0;
            while (bytesRead < bytesToRead)
            {
                var newBytes = await networkStream.ReadAsync(buffer, bytesRead, buffer.Length);
                if (newBytes == 0)
                {
                    throw new Exception("Socket Closed");
                }
                bytesRead += newBytes;
            }
            return buffer;
        }

        protected (byte[] header, byte[] body) Encode<T>(T message)
        {
            var bodyBytes = EncodeBody(message);
            var headerBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(bodyBytes.Length));
            return (headerBytes, bodyBytes);
        }

        protected abstract TMessageType Decode(byte[] message);

        protected abstract byte[] EncodeBody<T>(T messageType);

        protected virtual void AssertValidMessageLength(int messageLength)
        {
            if (messageLength < 1)
            {
                throw new Exception("Invalid Length");
            }
        }
    }

JSON协议类

   public class JsonMessageProtocal : Protocol<JObject>
    {
        static readonly JsonSerializer _serializer;
        static readonly JsonSerializerSettings _settings;

        static JsonMessageProtocal()
        {
            _settings = new JsonSerializerSettings
            {
                Formatting = Formatting.Indented,
                DateTimeZoneHandling = DateTimeZoneHandling.Utc,
                ContractResolver = new DefaultContractResolver
                {
                    NamingStrategy = new CamelCaseNamingStrategy
                    {
                        ProcessDictionaryKeys = false
                    }
                }
            };
            _serializer = JsonSerializer.Create(_settings);
        }

        protected override JObject Decode(byte[] message)
        {
            return JObject.Parse(Encoding.UTF8.GetString(message));
        }

        protected override byte[] EncodeBody<T>(T messageType)
        {
            var sb = new StringBuilder();
            var sr = new StringWriter(sb);
            _serializer.Serialize(sr, messageType);
            return Encoding.UTF8.GetBytes(sb.ToString());
        }
    }

XML协议类

TODO

通信信息适配

   [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class RouteAttribute : Attribute
    {
        public string Path { get; }

        public RouteAttribute(string path) => Path = path;
    }

    public abstract class MessageDispatcher<TMessageType> where TMessageType : class, new()
    {
        public abstract void Register<TParm, TResult>(Func<TParm, Task<TResult>> target);

        public abstract void Register<TParm>(Func<TParm, Task> target);

        public abstract Task<TMessageType> DispatchAsync(TMessageType message);
    }

    public class XDocumentMessageDispatch : MessageDispatcher<XDocument>
    {
        readonly List<(string xpathExpresstion, Func<XDocument, Task<XDocument>> targerMethod)> _handlers
            = new List<(string xpathExpresstion, Func<XDocument, Task<XDocument>> targerMethod)>();
        public override async Task<XDocument> DispatchAsync(XDocument message)
        {
            foreach (var (path, target) in _handlers)
            {
                if ((message.XPathEvaluate(path) as bool?) == true)
                {
                    return await target(message);
                }
            }
            return null;
        }

        public override void Register<TParm, TResult>(Func<TParm, Task<TResult>> target)
        {
            throw new NotImplementedException();
        }

        public override void Register<TParm>(Func<TParm, Task> target)
        {
            throw new NotImplementedException();
        }

        private string GetXPathRoute(MethodInfo methodInfo)
        {
            var routeAttribute = methodInfo.GetCustomAttribute<RouteAttribute>();
            if (routeAttribute == null)
                throw new ArgumentException($"Method { methodInfo.Name} missing required RouteAttribute");
            return $"boolean ({routeAttribute.Path})";
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c# TCP通信编程 的相关文章

  • 不调用bind()的情况下监听()

    我尝试了以下方法 int sockfd socket listen sockfd 10 accept sockfd 没有一个调用失败 并且程序开始阻塞 就像我调用了bind 一样 在这种情况下会发生什么 由于没有本地地址或端口 是否永远无法
  • 指示远程主机已关闭连接的 NetworkStream.Read 的替代方案?

    关于使用以下命令处理 TCP IP 连接TcpClient类 除了等待之外 还有其他方法可以检查远程主机是否已关闭连接吗 NetworkStream Read返回0的方法 您可以使用IOControlCode KeepAliveValues
  • Indy TCP - 循环读取数据

    TCP 服务器每 8 毫秒连续发送一次数据帧 我想编写一个能够接收这些数据帧的客户端 Indy 9 中是否有任何程序可以知道缓冲区中是否有可用数据 我当前的程序如下 我正在使用线程 procedure TThreadRead Execute
  • TCPServer 具有同时全双工通信

    我正在尝试编写一个 C 服务器 客户端 它将同时通过 TCP 相互发送字节数组 我正在努力思考如何实现这一目标 我见过的所有示例都等待消息 然后发送响应 我需要同时进行沟通 我是否需要为服务器和客户端上的传入和传出创建 2 个单独的 TCP
  • 如何进行 TCP 打孔?

    问题如下 这是我当前的测试代码 但没有成功 static void Main string args if args Count 3 Console WriteLine Bad args var ep new IPEndPoint IPAd
  • Python。从 6 字节字符串中打印 mac 地址

    我有 6 字节字符串的 mac 地址 您将如何以 人类 可读的格式打印它 Thanks import struct x x x x x x struct unpack BBBBBB your variable with mac
  • 如何识别用户空间和内核空间之间的特定套接字?

    我在用户空间中有一个库 可以拦截套接字层调用 例如socket connect accept 等等 我只处理 TCP 套接字 在内核空间中 我有一个网络内核模块 它处理所有 TCP 连接 我需要能够在驱动程序中识别哪些套接字被用户空间库拦截
  • 套接字编程Python:如何确保收到完整消息?

    我正在使用 python 3 x 和套接字模块 服务器在 ipv4 地址上运行并使用 tcp 我阅读了一些有关如何发送和接收数据的教程 对于服务器或客户端 要确保发送整个消息 您可以简单地检查发送的数据量是否等于消息的大小 def myse
  • wireshark 和 tcpdump -r:奇怪的 tcp 窗口大小

    我正在使用 tcpdump 捕获 http 流量 并且对 TCP 慢启动以及窗口大小如何增加感兴趣 sudo tcpdump i eth1 w wget tcpdump tcp and port 80 当我使用 Wireshark 查看转储
  • Socat未关闭tcp连接

    I use socat 1 7 3 1 r0并在alpine 3 3linux服务器 socat d d d PTY link dev ttyFOOBAR echo 0 raw unlink close 0 TCP LISTEN 7000
  • 我的代码中某处存在无限循环

    我有这个 Java 游戏服务器 最多可处理 3 000 个 tcp 连接 每个玩家或每个 tcp 连接都有自己的线程 每个线程的运行情况如下 public void run try String packet char charCur ne
  • 什么是消息边界?

    什么是 消息边界 在以下情况下 TCP 和 UDP 之间的区别之一是 UDP 保留消息 边界 我理解之间的区别TCP and UDP 但我不确定的定义 消息边界 由于 UDP 在每个单独的数据包中包含目的地和端口信息 因此是否可以为消息提供
  • 由于将请求从主线程传递到工作线程,netty 中出现延迟?

    我有一些关于 Netty 服务器端 TCP IP 应用程序的问题 我想知道在将请求从老板线程传递到工作线程时是否会因为 netty 由于缺少配置等 而出现延迟 我在用 new OrderedMemoryAwareThreadPoolExec
  • 使用 iPhone 作为热点时 TCP 连接无法正常工作

    我正在开发一个 iOS 应用程序 它通过 TCP 套接字连接到在 Android 上运行的服务器应用程序 为了找到第二个设备的 IP 我使用 UDP 请求并接收服务器的 IP 当我将它们连接到 Wi Fi 网络或使用 Android 设备作
  • net.TCPConn 允许在 FIN 数据包后写入

    我正在尝试为一些服务器端代码编写单元测试 但我在确定关闭测试用例时遇到了困难 环回 TCP 连接似乎无法正确处理干净关闭 我在一个示例应用程序中重现了这一点 该应用程序按顺序执行以下操作 创建客户端和服务器连接 通过从客户端向服务器成功发送
  • Linux环境下串口数据转换为TCP/IP

    我需要从Linux系统的串口获取数据并将其转换为TCP IP发送到服务器 这很难做到吗 我有一些基本的编程经验 但对 Linux 的经验不多 有没有开源应用程序可以做到这一点 在 Linux 中您不需要编写程序来执行此操作 只是pipe h
  • 数据包丢失和数据包重复

    我试图找出数据包丢失和数据包重复问题之间的区别 有谁知道 数据包重复 是什么意思 和TCP检测到丢失时重传数据包一样吗 No In TCP 数据包 的传递是可靠的 我认为在这种情况下术语数据应该更好 因为它是面向流的协议 数据包丢失和重复是
  • Python套接字模块:Recv()数据响应被切断

    解释 我目前正在尝试使用 python 脚本控制智能电源板 为了实现这一点 我使用了带有套接字模块的 TCP 连接 大约 75 的情况下 我会得到我正在寻找的响应 数据 并且一切都运行良好 然而 大约 25 的情况下 响应会以完全相同的长度
  • ZeroMQ可以用来接受传统的套接字请求吗?

    我正在尝试使用 ZeroMQ 重写我们的旧服务器之一 现在我有以下服务器设置 适用于 Zmq 请求 using var context ZmqContext Create using var server context CreateSoc
  • AMQP如何克服直接使用TCP的困难?

    AMQP如何克服直接使用TCP发送消息时的困难 或者更具体地说 在发布 订阅场景中 在 AMQP 中 有一个代理 该代理接收消息 然后完成将消息路由到交换器和队列的困难部分 您还可以设置持久队列 即使客户端断开连接 也可以为客户端保存消息

随机推荐

  • gdb反汇编disassemble

    GDB Command Reference disassemble command gdb反汇编可用disassemble disass命令 用法如下 xff1a disassemble disassemble Function 指定要反汇
  • S.M.A.R.T. 参数(smartctl)计算硬盘精确健康值

    参考 xff1a Acronis Drive Monitor Disk Health Calculation 文章目录 1 背景2 smartctl a dev sda3 计算健康值3 1 关键参数3 1 1 公式说明3 2 2 计算举例
  • python脚本——通过telnet连接设备

    文章目录 一 说明二 代码三 用法总结 一 说明 通过telnetlib库 xff0c telnet到设备上并做一些测试 包括重启设备 等待重启完成 其它测试操作等 二 代码 span class token comment usr bin
  • lspci 命令详解及常用命令

    文章目录 一 说明二 参数说明三 用法举例 一 说明 lspci是查看设备上pcie设备信息的命令 该命令的不同参数配合 xff0c 在查看pcie设备和定位pcie问题时很有用 包括查看pcie设备中断号 查看配置空间内容 修改配置空间寄
  • 中断模式和polling模式 && 硬件中断和软件中断

    文章目录 一 总结在前二 中断2 1 硬件中断与软件中断2 1 1 对比2 1 2 硬件中断2 1 3 软件中断 三 polling 一 总结在前 S NOInterruptPolling1中断模式下 xff0c 设备通知CPU有业务需要被
  • dma_alloc_coherent 申请内存用法和问题总结

    文章目录 1 dma alloc coherent用法2 问题3 解决方法方法一 xff0c 走CMA空间配置3 1 内核配置 96 96 CONFIG CMA 96 96 3 2 修改cma起始地址3 3 设置cma空间 xff08 大小
  • hadoop之HDFS:通过Java API访问HDFS

    HDFS是一个分布式文件系统 xff0c 可以通过Java API接口对HDFS进行操作 xff0c 下面记录实现Java API的过程和出现的一些问题及解决方案 环境搭建 导入jar包 common包中的jar文件导入 hadoop 2
  • sonic开发——修改内核配置

    参考 xff1a https github com Azure sonic linux kernel sonic 中的内核配置修改不需要编译menuconfig xff0c 而是直接修改 patch kconfig exclusions和p
  • 计算机内存管理之内存访问

    文章目录 一 设备I O内存访问ioremap amp ioremap nocacheioremap cachedioremap wc amp ioremap wtI O内存访问流程 二 设备地址映射到用户空间mmap过程 三 devmem
  • 内存管理之预留内存

    文章目录 一 memblock二 cmdline 有时候 xff0c 我们需要预留一段内存不受内核直接管理分配 xff0c 有什么办法 xff1f 一 memblock mmeblock是内存的一种管理机制 xff0c 主要管理这两种内存
  • 远程工作的一些命令

    文章目录 git配置ssh免密登录sshfs映射远程目录linux远程控制其它主机vscode ssh失败 git配置 git config global user name usrname git config global user e
  • 机器视觉-相机标定及畸变矫正

    摘要 xff1a 本文首先介绍了针孔相机模型 xff08 线性模型 xff09 xff0c 然后推导四个坐标轴变换的关系 xff0c 引出R T K D中包含相机的5个内参 xff0c 6个外参 然后介绍相机畸变的原因以及畸变模型 xff0
  • STM32的寄存器操作

    STM32最基本的 xff0c 最底层的 xff0c 就是对寄存器的直接操作 通过操作特定寄存器的特定位 xff0c 来实现相对应的功能 本文通过GPIO点亮LED来演示 GPIO 查阅数据手册 xff0c 了解相关内容 启动代码 旧版的k
  • STM32之RTOS:uCOS和FreeRTOS

    RTOS全称是 Real Time Operating System xff0c 中文就是实时操作系统 RTOS是指一类系统 xff0c 如 uC OS xff0c FreeRTOS xff0c RTX xff0c RT Thread 等
  • 树莓派3b系统Ubuntumate16下的tightvnc或xrdp远程控制开机启动

    本文主要是树莓派3b系统Ubuntumate16下 xff0c tightvnc开机自启动的爬坑经验 xff0c 这一技术极大便利了我们在手机 电脑端 xff0c 远程控制树莓派等基于liux系统的移动开发硬件 实现的过程从0到1 xff0
  • 关于spring-boot-maven-plugin插件爆红问题

    关于spirngboot打包插件爆红 xff0c 也就是 Plugin org springframework boot spring boot maven plugin not found错误问题 网上找了一大堆方法试了还是爆红 xff0
  • 198个经典C#WinForm实例源码(超赞)

    198个经典C WinForm实例源码 1 窗体 2 控件 3 图像 4 报表 5 系统 6 文件 7 网络 8 数据库 9 加密 解密 10 硬件读写 01 窗体技巧02 控件操作03 图像操作04 报表打印06 系统操作07 文件处理0
  • MySQL8.0.12重置root密码

    在安装完数据库后 xff0c 由于自己不小心直接关闭了安装窗口 xff0c 或者长时间没有使用root用户登录系统 xff0c 导致忘记了root密码 xff0c 这时就需要重置MySQL的root密码 当然 xff0c 最简单方式自然是删
  • 解决方法集合CondaHTTPError:HTTP 000 CONNECTION FAILED for url<https://mirrors.tuna.tsinghua.edu.cn/anaco

    目录 背景 解决方案 主要原因 xff1a 配置没配对 方法A xff1a 在cmd输入 方法B xff1a 修改 condarc xff08 运行期配置文件 xff09 其他原因 原因A xff1a 开了代理或者VPN 原因B xff1a
  • c# TCP通信编程

    目录 协议类JSON协议类XML协议类 通信信息适配 协议类 span class token keyword public span span class token keyword abstract span span class to