美文网首页
Netty编解码

Netty编解码

作者: 诺之林 | 来源:发表于2018-07-06 11:39 被阅读31次

本文的示例代码参考NettyCoder

目录

Startup

本文基于Netty入门NettyBasic项目

cp -R NettyBasic NettyCoder

mv ./src/main/java/com/example/NettyBasic ./src/main/java/com/example/NettyCoder

mv ./src/test/java/com/example/NettyBasic ./src/test/java/com/example/NettyCoder

grep -rl 'NettyBasic' * | xargs sed -i "" 's/NettyBasic/NettyCoder/g'
  • 测试
# server
./gradlew bootrun

# client
telnet 127.0.0.1 10001
# server
read: hello
read complete
read: world
read complete

# client
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello
world

String

vim client.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import socket
import unittest


HOST = '127.0.0.1'
PORT = 10001
ADDR = (HOST, PORT)


class Tests(unittest.TestCase):

    def setUp(self):
        self.socket = socket.socket(
            socket.AF_INET, socket.SOCK_STREAM)  # TCP socket
        self.socket.connect(ADDR)

    def tearDown(self):
        self.socket.close()

    def test_send_string(self):
        data = bytearray('message', 'utf-8')
        self.socket.send(data)


if __name__ == '__main__':
    unittest.main()

本文基于Python3 安装方法: "brew upgrade python" 或者 pyenv

  • 测试
# server
./gradlew bootrun

# client
python3 client.py
# server
server start
read: message
read complete
read complete

# client
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

Integer

vim client.py
# 这里省略了未修改代码

class Tests(unittest.TestCase):

    def setUp(self):
        self.socket = socket.socket(
            socket.AF_INET, socket.SOCK_STREAM)  # TCP socket
        self.socket.connect(ADDR)

    def tearDown(self):
        self.socket.close()

    # def test_send_string(self):
    #     data = bytearray('message', 'utf-8')
    #     self.socket.send(data)

    def test_send_integer(self):
        i = 1
        data = bytearray(i.to_bytes(4, 'big'))
        self.socket.send(data)

# 这里省略了未修改代码
vim src/main/java/com/example/NettyCoder/ByteToIntegerDecoder.java
package com.example.NettyCoder;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

public class ByteToIntegerDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if (in.readableBytes() >= 4) {
            out.add(in.readInt());
        }
    }
}
sed -i "" 's/StringDecoder()/ByteToIntegerDecoder()/g' ./src/main/java/com/example/NettyCoder/NettyServer.java
  • 测试
# server
./gradlew bootrun

# client
python3 client.py
# server
server start
read: 1
read complete
read complete

# client
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

字节序

关于字节序的概念 详细可以参考字节顺序 & 理解字节序

python3
Python 3.7.0 (default, Jun 29 2018, 20:13:13)
[Clang 9.1.0 (clang-902.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> i = 1
>>> print(i.to_bytes(4, 'big'))
b'\x00\x00\x00\x01'
>>> print(i.to_bytes(4, 'little'))
b'\x01\x00\x00\x00'
sed -i "" 's/big/little/g' ./client.py
  • 测试
# server
./gradlew bootrun

# client
python3 client.py
# server
server start
read: 16777216
read complete
read complete

# client
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

互动: 为什么服务端打印的结果是16777216?

Frame

vim client.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import socket
import unittest


HOST = '127.0.0.1'
PORT = 10001
ADDR = (HOST, PORT)

class Frame(object):

    def __init__(self, module, content):
        self.module = module
        self.content = content

    def toBytes(self):
        b1 = bytearray(self.module.to_bytes(4, 'big'))
        b2 = bytearray(self.content, 'utf-8')
        return b1 + b2


class Tests(unittest.TestCase):

    def setUp(self):
        self.socket = socket.socket(
            socket.AF_INET, socket.SOCK_STREAM)  # TCP socket
        self.socket.connect(ADDR)

    def tearDown(self):
        self.socket.close()

    # def test_send_string(self):
    #     data = bytearray('message', 'utf-8')
    #     self.socket.send(data)

    # def test_send_integer(self):
    #     i = 1
    #     data = bytearray(i.to_bytes(4, 'big'))
    #     self.socket.send(data)

    def test_send_frame(self):
        frame = Frame(1, "message")
        data = frame.toBytes()
        self.socket.send(data)


if __name__ == '__main__':
    unittest.main()
vim src/main/java/com/example/NettyCoder/Frame.java
package com.example.NettyCoder;

public class Frame {

    private int module;

    private String content;

    public int getModule() {
        return module;
    }

    public void setModule(int module) {
        this.module = module;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "Frame{" +
                "module=" + module +
                ", content='" + content + '\'' +
                '}';
    }
}
vim src/main/java/com/example/NettyCoder/FrameDecoder.java
package com.example.NettyCoder;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

public class FrameDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if (in.readableBytes() >= 11) {
            Frame frame = new Frame();
            frame.setModule(in.readInt());
            byte[] content = new byte[7];
            in.readBytes(content);
            frame.setContent(new String(content));
            out.add(frame);
        }
    }
}
sed -i "" 's/ByteToIntegerDecoder()/FrameDecoder()/g' ./src/main/java/com/example/NettyCoder/NettyServer.java
  • 测试
# server
./gradlew bootrun

# client
python3 client.py
# server
server start
read: Frame{module=1, content='message'}
read complete
read complete

# client
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

互动: 请大家思考经纬度和时间的编解码方式

参考

相关文章

  • Netty 心跳服务之 IdleStateHandler 源码分

    前言:Netty 提供的心跳介绍 Netty 作为一个网络框架,提供了诸多功能,比如我们之前说的编解码,Netty...

  • 自顶向下深入分析Netty(八)--CodecHandler

    编解码处理器作为Netty编程时必备的ChannelHandler,每个应用都必不可少。Netty作为网络应用框架...

  • Netty编解码

    本文的示例代码参考NettyCoder 目录 Startup String Interger字节序 Frame S...

  • Netty之六编解码器和handler的调用机制

    个人专题目录 1. Netty编解码器和handler的调用机制 1.1 基本说明 netty的组件设计:Nett...

  • JAVA-每日一面 2022-01-23

    为什么选择 Netty以及Netty 的使用场景 API使用简单,开发门槛低; 功能强大,预置了多种编解码功能,支...

  • Netty私有协议栈设计

    Netty私有协议栈设计 消息定义 消息头 消息主体 图示: Header: NettyMessage 编解码设计...

  • IM聊天系统

    编解码 protobuf 视频 webrtc 服务器netty 传送门:https://github.com/zh...

  • Netty编解码总结

    背景 TCP协议是个“流”性质协议,它的底层根据二进制缓冲区的实际情况进行包的划分,会把上层(Netty层)的By...

  • netty的编解码

    什么是拆包/粘包 TCP 粘包/拆包 半包:读取的数据不是一个数据包粘包:读取的数据超过一个数据包 粘包问题的解决...

  • 使用Netty编写一个极简的Http服务器

    Netty是一个高性能的网络编程框架,有着简单易于使用的抽象模型。利用Netty自带的Http协议编解码器,我们可...

网友评论

      本文标题:Netty编解码

      本文链接:https://www.haomeiwen.com/subject/ffpcuftx.html