Netty Hello World
When you read an article about async programming in java you will definitely find at least mentions of Netty. I’ve heard about this library, I know that many high-performance frameworks based on Netty (Akka, Vert.x, the full list is here), but I’ve never tried it. So it’s time to write a hello world application using Netty and scala.
What is Netty
Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.
Netty operates with Channels which are abstractions over a socket. As you may see, data can be read from or written to them - all these operations will be non-blocking. In addition, you can combine channels in groups and execute the same operations as for individual channels. If you’re creating server application you need some of the implementations of
ServerSocketChannel. To start working with a server channel, we have to introduce another important thing - thread pools which all the magic will be run on. There are two thread pools which should be passed to the server channel: boss and workers.
The boss one is going to accept incoming connections while the workers process these accepted connections.
What are we going to create
To capture images from the camera, we’ll use webcam-capture. It’s written in pure java and has very simple api.
All the code split into two parts: server side and client side. Due to the fact that I’m learning scala, the server side will be written in scala in java-style (I’m trying to adopt canonical, functional style, but this is tough to do very fast)
As you see, we don’t have many lines of code (thanks, scala!). Let’s go through the all key parts of this code.
There are two methods: the first one connects to default camera and starts capturing images (the details of this process won’t be covered in this article), the second one starts a web server.
To define a server, there is a special class
ServerBootstrap which is a
ServerChannel but with a simplified interface for server creation. It provides builder-style approach for its configuration. Here are main configuration steps:
group- takes two event loops, the firs one is for accepting incoming connections, the second one is for data processing
channel- takes a type of the channel that will be created
childHandler- takes a
ChannelHandlerthat will initialize a channel. In our case, it is a
ChannelInitializer. Its implementation is described below
The last step is
bind, that binds our channel to given port and returns a
ChannelFuture is used for correct closing of the server channel.
Now let’s go back to
ChannelInitializer. The most interesting part of it is pipeline. Pipeline passes all the date through a chain of
ChannelHandlers. In our case, we have
HttpServerCodec which is a http protocol implementation,
WebSocketServerProtocolHandler easily implements WebSockets (it requires
HttpObjectAggregator) and the last one
WebSocketFrameHandler which is our handler that does simple thing - it add newly connected client to the group of channels. This group is used in parallel thread that captures image and puts the binary into the group. Very simple!
As per our requirements, the client application should connect to a websocket and render an image once it comes to the client side. Here is all that we need:
This is pure javascipt. We even don’t need jQuery. The first part is standard WebSocket initialization - nothing to comment on it. There are two functions which should be described.
arrayBufferToBase64 takes ArrayBuffer (WebSocket in
socket.binaryType = "arraybuffer" mode uses this type of object to pass binaries) and converts to Base64 string. I haven’t written this function, I’ve stolen it from here. And the last key function here is
draw - when we have Base64 binaries of an image we can draw it on a canvas and this is a typical code to do so.