Netty编解码

2018-07-06  本文已影响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

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

参考

上一篇下一篇

猜你喜欢

热点阅读