简体   繁体   中英

With Netty, how can you store state per socket connection?

I'm using Netty to write a simple server application. It will accept long-running socket connections (ie telnet/ssh)... receiving string-based commands and sending string-based responses.

I need to track some session state, about the particular entity on the client end of that socket connection. I'm unclear on how to go about this.

A channel handler, through the ChannelHandlerContext objects passed to its channelRead(...) method, can access "attributes". However, this appears to be for setting state at the channel handler level , not the per socket connection level . The Javadocs for AttributeMap clearly state: " Be aware that it is not be possible [sic] to have multiple keys with the same name ". Most of the examples out there use this for simple "counter" illustrations.

There was a ChannelLocal class in earlier versions of Netty, that might have been relevant. But it has been removed as of Netty 4.x, and I think that it too was for handler-level state rather than connection-level state.

IS there a way have per-connection state, while still using the @Sharable annotation on your channel handler class, and taking full advantage of Netty's non-blocking benefits? Or is the approach for this use case simply to place instance variables on your channel handler, drop the @Shareable annotation, and spawn a new connection handler (and therefore new thread?) for each incoming connection?

Channel does extend AttributeMap , so you can just set/get attributes on the channel. A Channel is the abstraction for a socket connection.

On the other hand, there is nothing wrong with creating a ChannelHandler per Channel and save state in their field. A ChannelHandler has nothing to do with threads, those are abstracted by EventLoop s and there is only one EventLoop per Channel .

It is actually the other way round: a ChannelHandler is guaranteed to be called by the same thread (the Channel 's event loop, or the event loop specified when adding the handler to the Pipeline ). Thanks to this you do not need either synchronization nor the volatile qualifier for the fields of your channel handler.

You should annotate your ChannelHandler with @Sharable then store connection-specific attributes in the ChannelHandlerContext using attr() . This is very well-explained in ChannelHandlerContext documentation : "A handler can have more than one context".

Don't use ThreadPerChannelEventLoop , it breaks the abstraction over the threading model.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM