brief introduction
UDT is a very excellent protocol, which can provide high-speed data transmission based on UDP protocol. Unfortunately, in netty 4.1.7, the UDT transport protocol has been marked as Deprecated!
This means that you may never see the UDT protocol in the later netty version
How can excellent protocols be buried? Let's unveil UDT, show its excellent features, and let netty love UDT again.
netty support for UDT
Netty's support for UDT is reflected in a special UDT package to handle UDT related things: package io netty. channel. udt.
This package mainly defines various UDT channels, channel configurations, UDT messages, and tool classes NioUdtProvider that provide ChannelFactory and SelectorProvider
Build a netty service that supports UDT
According to the standard process of netty, it is time to create a netty service.
netty creating a server service is nothing more than creating an EventLoop, creating a ServerBootstrap, binding an EventLoop, and specifying a channel type. It is very simple.
The only difference is the specific childHandler, which may use different processing methods according to different protocols.
Of course, if it is not NioSocketChannel, the corresponding ChannelFactory and SelectorProvider will also change.
Never mind. Let's first look at how to create a netty service that supports UDT:
final ThreadFactory acceptFactory = new DefaultThreadFactory("accept"); final ThreadFactory connectFactory = new DefaultThreadFactory("connect"); final NioEventLoopGroup acceptGroup = new NioEventLoopGroup(1, acceptFactory, NioUdtProvider.BYTE_PROVIDER); final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, connectFactory, NioUdtProvider.BYTE_PROVIDER); final ServerBootstrap boot = new ServerBootstrap(); boot.group(acceptGroup, connectGroup) .channelFactory(NioUdtProvider.BYTE_ACCEPTOR) .option(ChannelOption.SO_BACKLOG, 10) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<UdtChannel>() { @Override public void initChannel(final UdtChannel ch) { ch.pipeline().addLast( new LoggingHandler(LogLevel.INFO), new UDTEchoServerHandler()); } }); // Open service final ChannelFuture future = boot.bind(PORT).sync();
It can be seen that the difference between UDT and ordinary netty socket service is that its selector and channelFactory are provided by NioUdtProvider.
NioUdtProvider is the content of netty core package. It provides useful encapsulation of UDT. We don't need to know too much about the internal implementation of UDT to use UDT protocol. Isn't it wonderful.
Abnormal attack
If a partner excitedly tries to run the above code, it is a pity that you will get an exception, which is probably similar to the following:
package com.barchart.udt can't find!
what? Using the class in the netty package directly will report an error? Who can bear it!
Let's analyze carefully. There is only one new class here, NioUdtProvider. Open the source code of NioUdtProvider. In the import column, we are surprised to find that packages that do not belong to netty are referenced. These packages report errors:
import com.barchart.udt.SocketUDT; import com.barchart.udt.TypeUDT; import com.barchart.udt.nio.ChannelUDT; import com.barchart.udt.nio.KindUDT; import com.barchart.udt.nio.RendezvousChannelUDT; import com.barchart.udt.nio.SelectorProviderUDT;
Although it's weird, we still need to find these dependency packages to run the program. After my hard work, I finally found the following dependency packages:
<dependency> <groupId>com.barchart.udt</groupId> <artifactId>barchart-udt-core</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.barchart.udt</groupId> <artifactId>barchart-udt-bundle</artifactId> <version>2.3.0</version> </dependency>
Netty's core package actually depends on a third-party library, which may be why netty is ready to remove its support for UDT.
TypeUDT and KindUDT
If you look at the specific information of classes in barchart, you will find that the author of this package has a hobby. He likes to bring a UDT behind the class.
When you see that all classes on the full screen end in UDT, yes, it is the package barchart that netty UDT depends on.
We can't say that the package developed by Daniel is bad, but it looks a little tired
In the barchart package, there are two core classes used to distinguish UDT type and kind, called TypeUDT and KindUDT respectively
Type and kind don't seem to make much difference when translated into Chinese. However, there are still great differences between the two in UDT.
TypeUDT represents the pattern of UDT socket. It has two values, stream and datagram:
STREAM(1), DATAGRAM(2),
Indicates whether the data transmission is in the form of byte stream or in the format of data message.
KindUDT is used to distinguish between server and client. It has three modes:
ACCEPTOR, CONNECTOR, RENDEZVOUS
The server mode corresponds to the ACCEPTOR, which is used to listen and receive connections Its representative is ServerSocketChannelUDT, which returns a CONNECTOR by calling the accept() method
The CONNECTOR mode can be used on both the client side and the server side. Its representative class is SocketChannelUDT
If it is on the server side, it is generated by calling the accept method on the server side. If it is on the client side, it indicates the connection between the client side and the server side.
Another mode is the RENDEZVOUS mode. This pattern means that each side of the connection has symmetrical and equivalent channels. That is, a two-way pattern. Its representative class is RENDEZVOUS channel UDT.
Building ChannelFactory
The two types and three Kind mentioned above are used to define channels, so if they are mixed, six different channelfactories will be generated, namely:
public static final ChannelFactory<UdtServerChannel> BYTE_ACCEPTOR = new NioUdtProvider<UdtServerChannel>( TypeUDT.STREAM, KindUDT.ACCEPTOR); public static final ChannelFactory<UdtChannel> BYTE_CONNECTOR = new NioUdtProvider<UdtChannel>( TypeUDT.STREAM, KindUDT.CONNECTOR); public static final ChannelFactory<UdtChannel> BYTE_RENDEZVOUS = new NioUdtProvider<UdtChannel>( TypeUDT.STREAM, KindUDT.RENDEZVOUS); public static final ChannelFactory<UdtServerChannel> MESSAGE_ACCEPTOR = new NioUdtProvider<UdtServerChannel>( TypeUDT.DATAGRAM, KindUDT.ACCEPTOR); public static final ChannelFactory<UdtChannel> MESSAGE_CONNECTOR = new NioUdtProvider<UdtChannel>( TypeUDT.DATAGRAM, KindUDT.CONNECTOR); public static final ChannelFactory<UdtChannel> MESSAGE_RENDEZVOUS = new NioUdtProvider<UdtChannel>( TypeUDT.DATAGRAM, KindUDT.RENDEZVOUS);
These channelfactories generate new channels by calling the newChannel() method.
However, in the root node, these channels finally call the from method of SelectorProviderUDT to generate channels.
SelectorProviderUDT
There are two kinds of SelectorProviderUDT according to different types of UDT, namely:
public static final SelectorProviderUDT DATAGRAM = new SelectorProviderUDT(TypeUDT.DATAGRAM); public static final SelectorProviderUDT STREAM = new SelectorProviderUDT(TypeUDT.STREAM);
You can generate the corresponding channel by calling its three methods:
public RendezvousChannelUDT openRendezvousChannel() throws IOException { final SocketUDT socketUDT = new SocketUDT(type); return new RendezvousChannelUDT(this, socketUDT); } public ServerSocketChannelUDT openServerSocketChannel() throws IOException { final SocketUDT serverSocketUDT = new SocketUDT(type); return new ServerSocketChannelUDT(this, serverSocketUDT); } public SocketChannelUDT openSocketChannel() throws IOException { final SocketUDT socketUDT = new SocketUDT(type); return new SocketChannelUDT(this, socketUDT); }
Using UDT
After setting up the netty server, the rest is to write a Handler to process the data.
Here we simply write back the data written by the client. The client creates a message first:
message = Unpooled.buffer(UDTEchoClient.SIZE); message.writeBytes("www.flydean.com".getBytes(StandardCharsets.UTF_8));
Then write to the server:
public void channelActive(final ChannelHandlerContext ctx) { log.info("channel active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); ctx.writeAndFlush(message); }
The server receives through the channelRead method:
public void channelRead(final ChannelHandlerContext ctx, Object msg) { ctx.write(msg); }
summary
The above is the principle of using UDT in netty and a simple example.
Examples of this article can be referred to: learn-netty4
This article has been included in http://www.flydean.com/40-netty-udt-support/
The most popular interpretation, the most profound dry goods, the most concise tutorial, and many tips you don't know are waiting for you to find!
Welcome to my official account: "those things in procedure", understand technology, know you better!