delphi中tidtcpserver如何给指定的客户端发送数据_如何自己设计一个RPC或HTTP协议服务框架...

本文介绍了如何设计一个通信框架,从Delphi TIdTCPServer出发,讲解协议设计、通信技术选择以及高性能高可靠性的考量。通过实例展示了如何创建数据模型、服务端和客户端,实现HTTP服务和RPC框架,并提及该框架可用于构建MQ消息系统。
摘要由CSDN通过智能技术生成

网络世界离不开的就是通信,不管是任何框架只要是提供互联网服务就必须有通信的能力。作为业务开发者可能我们业务中也会遇到这样的需求,或者是有啥好的创意性框架,但是无奈现在通信层框架都太厚重了,想要快速学习使用显然不太可能,所以呢 本文就是教你如何来实现一个封装一个通信层框架。

25c5c9d2ea7ebf1203a0349fa1b16492.gif

当看完本篇你将会对Java技术有一个更深入的了解。你可以利用本文学习的内容去实现一下业务

  • 自己设计一个Tomcat容器;
  • 自己设计一款RPC框架;
  • 也可以在你的应用程序内部去在启动一个通信服务。

文章后面有演示。项目github地址关注私信: 01 自动回复

d1a8701d9b75e41d0967eef50a3dcd7c.png

一、通信框架设计要考虑的点

通信肯定是双方间的,客户端发送数据,服务端处理数据。我们日常的开发都是基于http协议的,是不用考虑服务端和客户端如何去发送数据的。因为我们理解的数据都是明文的模型,而http协议底层会将其转换成二进制数据通过TCP/IP协议传递给服务端和客户端。而下面内容是要讨论的如何将明文数据转换成二进制数据,以及让客户端和服务端都能理解这样的二进制数据。

1. 什么是协议?以及如何去设计协议?

d7afa0bce7d6e3f828f55592f45a07d4.png

协议就是通信双方约定的明文和二进制数据的转换格式。客户端按照约定将明文数据转换成二进制数据,服务端按照约定将二进制数据转换成明文数据。

如我们约定读取的第一个字节是协议类型,第二个字节是序列化类型,第三个是报文长度,第四是报文内容。

0b25d615e34a7499810792536ccfed65.png

1.1 客户端根据协议去构建报文

那么客户端在发数据给服务端的时候就要根据前面定的协议去拼装二进制数据。

    @Override
    protected void doEncode(ChannelHandlerContext ctx, RpcProtocolHeader msg, ByteBuf out) throws Exception {
        //1. 获取协议类型(1个字节)
        out.writeByte(msg.getProtocolType());
        //2. 获取序列化类型(1个字节)
        out.writeByte(msg.getSerializationType());
        //3. 根据序列化类型找到数据转换器生成二进制数据
        Serializer serializer = SerializeEnum.ofByType(msg.getSerializationType()).getSerialize().newInstance();
        byte[] data = serializer.serialize(msg);
        //4. 写入报文长度(4个字节)
        out.writeInt(data.length);
        //5. 写入报文内容(数组)
        out.writeBytes(data);
    }

1.2 服务端根据协议去解析报文

这里通常会遇到很多问题,比如拆包和粘包问题

  • 拆包是说一个数据发送时候发送的是hello,但是服务端收到的是2次的请求,第一次是hel,第二次是lo。
  • 粘包是说发了客户端发了2次hello,但是服务端收到的是在一起的hellohello,两个报文粘在一起的。如果要自定义协议就必须要解决这两个问题,如何来解决呢? 其实很简单,就是要知道,报文什么时候结束的。就像上面的说的协议,为什么要把报文长度写放到报文里面呢? 前面的协议接受到的数据最少是6个字节。

1个字节的协议类型,1个字节的序列化类型,4个字节的数据长度,剩下的是数据包内容。

当服务端在处理二进制数据时候如果发现可读的字节不到6个字节,那肯定说明报文不完整,就先不处理,等待报文都到了在处理。如果到了6个字节,那么我们肯定就能知道真正的报文长度是多少,然后在读取真正的报文内容,就能知道什么时候报文是结束了。如果报文真正内容不够,继续等待,等待数据都到齐。


    @Override
    protected void doDecode(ChannelHandlerContext ctx, ByteBuf inByteBuf, List out) throws Exception {
        byte[] dataArr;
        //1. 不可读就关闭
        if (!inByteBuf.isReadable()) {
            Channel channel = ctx.channel();
            SocketAddress socketAddress = channel.remoteAddress();
            channel.close();
            System.err.println(">>>>>&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值