Netty for long-service client connection communication and heartbeat detection

Source: Internet
Author: User

Absrtact: The long connection between server and client is realized through Netty, and heartbeat detection

The long connection between server and client is realized through Netty, and heartbeat detection.

Basic idea: The Netty server saves all connected client Socketchannel through a map, and the client ID is the key to the map. Each time the server side wants to send a message to a client, simply take out the corresponding Socketchannel according to ClientID, and write the message to it. Heartbeat detection through the Idleevent event, timed to the server to broadcast a ping message to detect whether the socketchannel is broken.

Environmental JDK1.8 and Netty5

The following are specific code implementations and descriptions:

1 public Share section (mainly contains the definition of the Message protocol type)

Design Message Type:

public enum Msgtype {
Ping,ask,reply,login
}

Message base class:

must implement the sequence, Serialversionuid must have, no one in the Netty message serialization deserialization will be problematic, receive messages!!!
Public abstract class Basemsg implements Serializable {
Private static final long serialversionuid = 1L;
Rivate msgtype type;
Must be unique, no one will have channel call chaos
Private String clientId;

Initializing the Client ID
Public basemsg () {
This.clientid = Constants.getclientid ();
}

Public String Getclientid () {
return clientId;
}

public void Setclientid (String clientId) {
This.clientid = clientId;
}

Public Msgtype GetType () {
return type;
}

public void SetType (Msgtype type) {
This.type = type;
}
}

Constant settings:

public class Constants {
private static String clientId;

public static String Getclientid () {
return clientId;
}

public static void Setclientid (String clientId) {
Constants.clientid = clientId;
}
}

Logon Type message:

public class Loginmsg extends Basemsg {
Private String UserName;
private String password;
Public loginmsg () {
Super ();
SetType (Msgtype.login);
}

Public String GetUserName () {
return userName;
}

public void Setusername (String userName) {
This.username = UserName;
}

Public String GetPassword () {
return password;
}

public void SetPassword (String password) {
This.password = password;
}
}

Heartbeat detection Ping Type message:

public class Pingmsg extends Basemsg {
Public pingmsg () {
Super ();
SetType (msgtype.ping);
}
}

Request Type message:

public class Askmsg extends Basemsg {
Public askmsg () {
Super ();
SetType (Msgtype.ask);
}

Private Askparams params;

Public Askparams Getparams () {
return params;
}

public void SetParams (Askparams params) {
This.params = params;
}
}

Request Type Parameters
The serialization interface must be implemented
public class Askparams implements Serializable {
Private static final long serialversionuid = 1L;
Private String auth;

Public String GetAuth () {
return auth;
}

public void Setauth (String auth) {
This.auth = auth;
}
}

Response type message:

public class Replymsg extends Basemsg {
Public replymsg () {
Super ();
SetType (msgtype.reply);
}
Private Replybody body;

Public Replybody GetBody () {
return body;
}

public void Setbody (Replybody body) {
This.body = body;
}
}
Corresponding type body pair image
public class Replybody implements Serializable {
Private static final long serialversionuid = 1L;
}
public class Replyclientbody extends Replybody {
Private String Clientinfo;

Public Replyclientbody (String clientinfo) {
This.clientinfo = Clientinfo;
}

Public String Getclientinfo () {
return clientinfo;
}

public void Setclientinfo (String clientinfo) {
This.clientinfo = Clientinfo;
}
}
public class Replyserverbody extends Replybody {
Private String ServerInfo;
Public Replyserverbody (String serverinfo) {
This.serverinfo = ServerInfo;
}
Public String Getserverinfo () {
return serverinfo;
}
public void SetServerInfo (String serverinfo) {
This.serverinfo = ServerInfo;
}
}

2 server side: mainly contains the implementation and bootstrap of the Map,channelhandler referenced by Socketchannel.

MAP:

public class Nettychannelmap {
private static map<string,socketchannel> map=new concurrenthashmap<string, socketchannel> ();
public static void Add (String clientid,socketchannel socketchannel) {
Map.put (Clientid,socketchannel);
}
public static Channel Get (String clientId) {
Return Map.get (CLIENTID);
}
public static void Remove (Socketchannel socketchannel) {
For (Map.entry Entry:map.entrySet ()) {
if (Entry.getvalue () ==socketchannel) {
Map.Remove (Entry.getkey ());
}
}
}

}

Handler:

public class Nettyserverhandler extends Simplechannelinboundhandler<basemsg> {
@Override
public void Channelinactive (Channelhandlercontext ctx) throws Exception {
Channel invalidation, removing from map
Nettychannelmap.remove ((Socketchannel) Ctx.channel ());
}
@Override
protected void messagereceived (Channelhandlercontext channelhandlercontext, basemsg basemsg) throws Exception {

if (MsgType.LOGIN.equals (Basemsg.gettype ())) {
Loginmsg loginmsg= (loginmsg) basemsg;
if ("Robin". Equals (Loginmsg.getusername ()) && "Yao". Equals (Loginmsg.getpassword ())) {
Log in successfully and save the channel to the server map
Nettychannelmap.add (Loginmsg.getclientid (), (Socketchannel) Channelhandlercontext.channel ());
SYSTEM.OUT.PRINTLN ("Client" +loginmsg.getclientid () + "login Success");
}
}else{
if (Nettychannelmap.get (Basemsg.getclientid ()) ==null) {
Description is not logged in, or the connection is broken, the server initiates a login request to the client to have the client log on again
Loginmsg loginmsg=new loginmsg ();
Channelhandlercontext.channel (). Writeandflush (LOGINMSG);
}
}
Switch (Basemsg.gettype ()) {
Case ping:{
Pingmsg pingmsg= (pingmsg) basemsg;
Pingmsg replyping=new pingmsg ();
Nettychannelmap.get (Pingmsg.getclientid ()). Writeandflush (replyping);
}break;
Case ask:{
Request received from client
Askmsg askmsg= (askmsg) basemsg;
if ("AuthToken". Equals (Askmsg.getparams (). GetAuth ())) {
Replyserverbody replybody=new replyserverbody ("Server info $!!!");
Replymsg replymsg=new replymsg ();
Replymsg.setbody (Replybody);
Nettychannelmap.get (Askmsg.getclientid ()). Writeandflush (REPLYMSG);
}
}break;
Case reply:{
Receive client reply
Replymsg replymsg= (replymsg) basemsg;
Replyclientbody clientbody= (Replyclientbody) replymsg.getbody ();
SYSTEM.OUT.PRINTLN ("Receive client msg:" +clientbody.getclientinfo ());
}break;
Default:break;
}
Referencecountutil.release (BASEMSG);
}
}

Serverbootstrap:

public class Nettyserverbootstrap {
private int port;
Private Socketchannel Socketchannel;
public nettyserverbootstrap (int port) throws Interruptedexception {
This.port = port;
Bind ();
}

private void Bind () throws Interruptedexception {
Eventloopgroup boss=new Nioeventloopgroup ();
Eventloopgroup worker=new Nioeventloopgroup ();
Serverbootstrap bootstrap=new serverbootstrap ();
Bootstrap.group (Boss,worker);
Bootstrap.channel (Nioserversocketchannel.class);
Bootstrap.option (Channeloption.so_backlog, 128);
Disable Nagle through Nodelay so that messages are sent out immediately without waiting for a certain amount of data to be sent out
Bootstrap.option (Channeloption.tcp_nodelay, true);
Maintain Long connection status
Bootstrap.childoption (channeloption.so_keepalive, true);
Bootstrap.childhandler (New channelinitializer<socketchannel> () {
@Override
protected void Initchannel (Socketchannel socketchannel) throws Exception {
Channelpipeline p = socketchannel.pipeline ();
P.addlast (New Objectencoder ());
P.addlast (New Objectdecoder (classresolvers.cachedisabled (null)));
P.addlast (New Nettyserverhandler ());
}
});
Channelfuture f= Bootstrap.bind (port). sync ();
if (f.issuccess ()) {
SYSTEM.OUT.PRINTLN ("Server Start---------------");
}
}
public static void Main (String []args) throws Interruptedexception {
Nettyserverbootstrap bootstrap=new Nettyserverbootstrap (9999);
while (true) {
Socketchannel channel= (Socketchannel) nettychannelmap.get ("001");
if (channel!=null) {
Askmsg askmsg=new askmsg ();
Channel.writeandflush (ASKMSG);
}
TimeUnit.SECONDS.sleep (5);
}
}
}

3 Client side: Includes initiating login, sending heartbeat, and corresponding message processing

Handler

public class Nettyclienthandler extends Simplechannelinboundhandler<basemsg> {
Send heartbeat detection messages with write idle
@Override
public void usereventtriggered (Channelhandlercontext ctx, Object evt) throws Exception {
if (evt instanceof idlestateevent) {
Idlestateevent e = (idlestateevent) evt;
Switch (e.state ()) {
Case Writer_idle:
Pingmsg pingmsg=new pingmsg ();
Ctx.writeandflush (PINGMSG);
System.out.println ("Send ping to Server----------");
Break
Default
Break
}
}
}
@Override
protected void messagereceived (Channelhandlercontext channelhandlercontext, basemsg basemsg) throws Exception {
Msgtype Msgtype=basemsg.gettype ();
Switch (msgtype) {
Case login:{
Initiating a login to the server
Loginmsg loginmsg=new loginmsg ();
Loginmsg.setpassword ("Yao");
Loginmsg.setusername ("Robin");
Channelhandlercontext.writeandflush (LOGINMSG);
}break;
Case ping:{
System.out.println ("Receive ping from Server----------");
}break;
Case ask:{
Replyclientbody replyclientbody=new replyclientbody ("Client Info * * * *!!!");
Replymsg replymsg=new replymsg ();
Replymsg.setbody (Replyclientbody);
Channelhandlercontext.writeandflush (REPLYMSG);
}break;
Case reply:{
Replymsg replymsg= (replymsg) basemsg;
Replyserverbody replyserverbody= (Replyserverbody) replymsg.getbody ();
SYSTEM.OUT.PRINTLN ("Receive client msg:" +replyserverbody.getserverinfo ());
}
Default:break;
}
Referencecountutil.release (Msgtype);
}
}

Bootstrap

public class Nettyclientbootstrap {
private int port;
Private String host;
Private Socketchannel Socketchannel;
Private static final Eventexecutorgroup group = new Defaulteventexecutorgroup (20);
public nettyclientbootstrap (int port, String host) throws Interruptedexception {
This.port = port;
This.host = host;
Start ();
}
private void Start () throws Interruptedexception {
Eventloopgroup eventloopgroup=new Nioeventloopgroup ();
Bootstrap bootstrap=new Bootstrap ();
Bootstrap.channel (Niosocketchannel.class);
Bootstrap.option (channeloption.so_keepalive,true);
Bootstrap.group (Eventloopgroup);
Bootstrap.remoteaddress (Host,port);
Bootstrap.handler (New channelinitializer<socketchannel> () {
@Override
protected void Initchannel (Socketchannel socketchannel) throws Exception {
Socketchannel.pipeline (). AddLast (New Idlestatehandler (20,10,0));
Socketchannel.pipeline (). AddLast (New Objectencoder ());
Socketchannel.pipeline (). AddLast (New Objectdecoder (classresolvers.cachedisabled (null)));
Socketchannel.pipeline (). AddLast (New Nettyclienthandler ());
}
});
Channelfuture future =bootstrap.connect (host,port). sync ();
if (future.issuccess ()) {
Socketchannel = (Socketchannel) future.channel ();
SYSTEM.OUT.PRINTLN ("Connect server successfully---------");
}
}
public static void Main (String[]args) throws Interruptedexception {
Constants.setclientid ("001");
Nettyclientbootstrap bootstrap=new Nettyclientbootstrap (9999, "localhost");

Loginmsg loginmsg=new loginmsg ();
Loginmsg.setpassword ("Yao");
Loginmsg.setusername ("Robin");
Bootstrap.socketChannel.writeAndFlush (LOGINMSG);
while (true) {
TimeUnit.SECONDS.sleep (3);
Askmsg askmsg=new askmsg ();
Askparams askparams=new askparams ();
Askparams.setauth ("AuthToken");
Askmsg.setparams (Askparams);
Bootstrap.socketChannel.writeAndFlush (ASKMSG);
}
}
}

Netty for long-service client connection communication and heartbeat detection

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.