美文网首页
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编解码

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