Spring + netty Server SETUP method, springnetty

Source: Internet
Author: User
Tags return tag

Spring + netty Server SETUP method, springnetty

Games are generally persistent connections, custom protocols, and http protocols are not required, BIO, NIO, or AIO.

I now use spring + netty to build a simple game server

Ideas: 1. custom protocol and Protocol package; 2. spring + netty integration; 3. Half-package stick packet processing; heartbeat mechanism; 4. Request distribution (currently we are working on Singleton Mode)
The next one is for testing. The structure is as follows:

First, customize the header

Header. java

Package com. test. netty. message;/*** Header. java * custom protocol Header * @ author janehuang * @ version 1.0 */public class Header {private byte tag;/* encoding */private byte encode; /* encrypt */private byte encrypt;/* Other fields */private byte extend1;/* Other 2 */private byte extend2;/* session id */private String sessionid; /* package length */private int length = 1024;/* command */private int cammand; public Header () {} public Header (String sessionid) {this. encode = 0; this. encrypt = 0; this. sessionid = sessionid;} public Header (byte tag, byte encode, byte encrypt, byte extend1, byte extend2, String sessionid, int length, int cammand) {this. tag = tag; this. encode = encode; this. encrypt = encrypt; this. extend1 = extend1; this. extend2 = extend2; this. sessionid = sessionid; this. length = length; this. cammand = cammand ;}@ Override public String toString () {return "header [tag =" + tag + "encode =" + encode + ", encrypt =" + encrypt + ", extend1 = "+ extend1 +", extend2 = "+ extend2 +", sessionid = "+ sessionid +", length = "+ length + ", cammand = "+ cammand +"] ";} public byte getTag () {return tag;} public void setTag (byte tag) {this. tag = tag;} public byte getEncode () {return encode;} public void setEncode (byte encode) {this. encode = encode;} public byte getEncrypt () {return encrypt;} public void setEncrypt (byte encrypt) {this. encrypt = encrypt;} public byte getExtend1 () {return extend1;} public void setExtend1 (byte extend1) {this. extend1 = extend1;} public byte getExtend2 () {return extend2;} public void setExtend2 (byte extend2) {this. extend2 = extend2;} public String getSessionid () {return sessionid;} public void setSessionid (String sessionid) {this. sessionid = sessionid;} public int getLength () {return length;} public void setLength (int length) {this. length = length;} public int getCammand () {return cammand;} public void setCammand (int cammand) {this. cammand = cammand ;}}

Package body. I use strings to convert bytecode for simple processing. Generally, many games use probuf to serialize data into binary.

Message. java

package com.test.netty.message;    import io.netty.buffer.ByteBuf;  import io.netty.buffer.Unpooled;   import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.UnsupportedEncodingException;   import com.test.netty.decoder.MessageDecoder;   /**  * Message.java  *   * @author janehuang  * @version 1.0  */  public class Message {      private Header header;      private String data;      public Header getHeader() {      return header;    }      public void setHeader(Header header) {      this.header = header;    }      public String getData() {      return data;    }      public void setData(String data) {      this.data = data;    }      public Message(Header header) {      this.header = header;    }      public Message(Header header, String data) {      this.header = header;      this.data = data;    }      public byte[] toByte() {      ByteArrayOutputStream out = new ByteArrayOutputStream();      out.write(MessageDecoder.PACKAGE_TAG);      out.write(header.getEncode());      out.write(header.getEncrypt());      out.write(header.getExtend1());      out.write(header.getExtend2());      byte[] bb = new byte[32];      byte[] bb2 = header.getSessionid().getBytes();      for (int i = 0; i < bb2.length; i++) {        bb[i] = bb2[i];      }        try {        out.write(bb);          byte[] bbb = data.getBytes("UTF-8");        out.write(intToBytes2(bbb.length));        out.write(intToBytes2(header.getCammand()));        out.write(bbb);        out.write('\n');      } catch (UnsupportedEncodingException e) {        // TODO Auto-generated catch block        e.printStackTrace();      } catch (IOException e) {        // TODO Auto-generated catch block        e.printStackTrace();      }      return out.toByteArray();    }      public static byte[] intToByte(int newint) {      byte[] intbyte = new byte[4];      intbyte[3] = (byte) ((newint >> 24) & 0xFF);      intbyte[2] = (byte) ((newint >> 16) & 0xFF);      intbyte[1] = (byte) ((newint >> 8) & 0xFF);      intbyte[0] = (byte) (newint & 0xFF);      return intbyte;    }      public static int bytesToInt(byte[] src, int offset) {      int value;      value = (int) ((src[offset] & 0xFF) | ((src[offset + 1] & 0xFF) << 8) | ((src[offset + 2] & 0xFF) << 16) | ((src[offset + 3] & 0xFF) << 24));      return value;    }      public static byte[] intToBytes2(int value) {      byte[] src = new byte[4];      src[0] = (byte) ((value >> 24) & 0xFF);      src[1] = (byte) ((value >> 16) & 0xFF);      src[2] = (byte) ((value >> 8) & 0xFF);      src[3] = (byte) (value & 0xFF);      return src;    }      public static void main(String[] args) {      ByteBuf heapBuffer = Unpooled.buffer(8);      System.out.println(heapBuffer);      ByteArrayOutputStream out = new ByteArrayOutputStream();      try {        out.write(intToBytes2(1));      } catch (IOException e) {        // TODO Auto-generated catch block        e.printStackTrace();      }      byte[] data = out.toByteArray();      heapBuffer.writeBytes(data);      System.out.println(heapBuffer);      int a = heapBuffer.readInt();      System.out.println(a);    }    }  

Decoder

MessageDecoder. java

Package com. test. netty. decoder; import io. netty. buffer. byteBuf; import io. netty. channel. channelHandlerContext; import io. netty. handler. codec. byteToMessageDecoder; import io. netty. handler. codec. corruptedFrameException; import java. util. list; import com. test. netty. message. header; import com. test. netty. message. message;/*** HeaderDecoder. java ** @ author janehuang * @ version 1.0 */public class Messa GeDecoder extends ByteToMessageDecoder {/** Packet Length header **/public static final int HEAD_LENGHT = 45;/** flag header **/public static final byte PACKAGE_TAG = 0x01; @ Override protected void decode (ChannelHandlerContext ctx, ByteBuf buffer, List <Object> out) throws Exception {buffer. markReaderIndex (); if (buffer. readableBytes () <HEAD_LENGHT) {throw new writable uptedframeexception ("packet length problem");} byte tag = buffer. read Byte (); if (tag! = PACKAGE_TAG) {throw new writable uptedframeexception ("flag error");} byte encode = buffer. readByte (); byte encrypt = buffer. readByte (); byte extend1 = buffer. readByte (); byte extend2 = buffer. readByte (); byte sessionByte [] = new byte [32]; buffer. readBytes (sessionByte); String sessionid = new String (sessionByte, "UTF-8"); int length = buffer. readInt (); int cammand = buffer. readInt (); Header header = new Header (tag, encode, encrypt, extend1, extend2, sessionid, length, cammand); byte [] data = new byte [length]; buffer. readBytes (data); Message message = new Message (header, new String (data, "UTF-8"); out. add (message );}}

Encoder

MessageEncoder. java

package com.test.netty.encoder; import com.test.netty.decoder.MessageDecoder; import com.test.netty.message.Header; import com.test.netty.message.Message;  import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder;   /**  * MessageEncoder.java  *  * @author janehuang  * @version 1.0  */ public class MessageEncoder extends MessageToByteEncoder<Message> {    @Override   protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {       Header header = msg.getHeader();       out.writeByte(MessageDecoder.PACKAGE_TAG);       out.writeByte(header.getEncode());       out.writeByte(header.getEncrypt());       out.writeByte(header.getExtend1());       out.writeByte(header.getExtend2());       out.writeBytes(header.getSessionid().getBytes());       out.writeInt(header.getLength());       out.writeInt(header.getCammand());       out.writeBytes(msg.getData().getBytes("UTF-8"));   }  } 

Server

TimeServer. java

package com.test.netty.server; import org.springframework.stereotype.Component; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.LineBasedFrameDecoder;  import com.test.netty.decoder.MessageDecoder; import com.test.netty.encoder.MessageEncoder; import com.test.netty.handler.ServerHandler; /**  * ChatServer.java  *  * @author janehuang  * @version 1.0  */ @Component public class TimeServer {    private int port=88888;   public void run() throws InterruptedException {     EventLoopGroup bossGroup = new NioEventLoopGroup();     EventLoopGroup workerGroup = new NioEventLoopGroup();     ByteBuf heapBuffer = Unpooled.buffer(8);     heapBuffer.writeBytes("\r".getBytes());     try {       ServerBootstrap b = new ServerBootstrap(); // (2)       b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // (3)           .childHandler(new ChannelInitializer<SocketChannel>() { // (4)                 @Override                 public void initChannel(SocketChannel ch) throws Exception {                   ch.pipeline().addLast("encoder", new MessageEncoder()).addLast("decoder", new MessageDecoder()).addFirst(new LineBasedFrameDecoder(65535))                       .addLast(new ServerHandler());                 }               }).option(ChannelOption.SO_BACKLOG, 1024) // (5)           .childOption(ChannelOption.SO_KEEPALIVE, true); // (6)       ChannelFuture f = b.bind(port).sync(); // (7)       f.channel().closeFuture().sync();     } finally {       workerGroup.shutdownGracefully();       bossGroup.shutdownGracefully();     }   }      public void start(int port) throws InterruptedException{    this.port=port;    this.run();   }  } 

Processor and distribution

ServerHandler. java

Package com. test. netty. handler; import io. netty. channel. channelHandlerAdapter; import io. netty. channel. channelHandlerContext; import com. test. netty. invote. actionMapUtil; import com. test. netty. message. header; import com. test. netty. message. message;/***** @ author janehuang **/public class ServerHandler extends ChannelHandlerAdapter {@ Override public void channelActive (ChannelHandlerContext ctx) throws Exception {String content = "I have received the connection "; header header = new Header (byte) 0, (byte) 1, (byte) 1, (byte) 1, (byte) 0, "713f17ca614361fb257dc6741332caf2", content. getBytes ("UTF-8 "). length, 1); Message message = new Message (header, content); ctx. writeAndFlush (message) ;}@ Override public void exceptionCaught (ChannelHandlerContext ctx, Throwable cause) {cause. printStackTrace (); ctx. close () ;}@ Override public void channelRead (ChannelHandlerContext ctx, Object msg) throws Exception {Message m = (Message) msg; // (1) /* request Distribution */ActionMapUtil. invote (header. getCammand (), ctx, m );}}

Distribution tool

ActionMapUtil. java

package com.test.netty.invote; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class ActionMapUtil {   private static Map<Integer, Action> map = new HashMap<Integer, Action>();    public static Object invote(Integer key, Object... args) throws Exception {     Action action = map.get(key);     if (action != null) {       Method method = action.getMethod();       try {         return method.invoke(action.getObject(), args);       } catch (Exception e) {         throw e;       }     }     return null;   }    public static void put(Integer key, Action action) {     map.put(key, action);   }  } 

Objects Created for Distribution

Action. java

package com.test.netty.invote;  import java.lang.reflect.Method;  public class Action {      private Method method;   private Object object;    public Method getMethod() {     return method;   }    public void setMethod(Method method) {     this.method = method;   }    public Object getObject() {     return object;   }    public void setObject(Object object) {     this.object = object;   } } 

Custom annotation, similar to @ Controller in springmvc

NettyController. java

package com.test.netty.core;  import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;  import org.springframework.stereotype.Component;  @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Component public @interface NettyController { } 

@ ReqestMapping in spring mvc

ActionMap. java

package com.test.netty.core; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;  @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface ActionMap {     int key();     } 

These annotations are added to save these objects to the container after spring initializes the bean. This bean needs to be configured in spring and will be called after spring bean is instantiated.

ActionBeanPostProcessor. java

package com.test.netty.core; import java.lang.reflect.Method; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import com.test.netty.invote.Action; import com.test.netty.invote.ActionMapUtil; public class ActionBeanPostProcessor implements BeanPostProcessor {   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {     return bean;   }    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {     Method[] methods=bean.getClass().getMethods();     for (Method method : methods) {       ActionMap actionMap=method.getAnnotation(ActionMap.class);       if(actionMap!=null){         Action action=new Action();         action.setMethod(method);         action.setObject(bean);         ActionMapUtil.put(actionMap.key(), action);       }     }     return bean;   } } 

Controller instance

UserController. java

Package com. test. netty. controller; import io. netty. channel. channelHandlerContext; import org. springframework. beans. factory. annotation. autowired; import com. test. model. userModel; import com. test. netty. core. actionMap; import com. test. netty. core. nettyController; import com. test. netty. message. message; import com. test. service. userService; @ NettyController () public class UserAction {@ Autowired private UserService userService; @ ActionMap (key = 1) public String login (ChannelHandlerContext ct, Message message) {UserModel userModel = this. userService. the findByMasterUserId (1000001); System. out. println (String. format ("user nickname: % s; password % d; descendant content % s", userModel. getNickname (), userModel. getId (), message. getData (); return userModel. getNickname ();}}

Remember to add the applicationContext. xml configuration file

<bean class="com.test.netty.core.ActionBeanPostProcessor"/> 

Test code

package test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.test.netty.server.TimeServer; public class Test {   public static void main(String[] args) {      ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");       TimeServer timeServer= ac.getBean(TimeServer.class);      try {       timeServer.start(8888);     } catch (InterruptedException e) {       // TODO Auto-generated catch block       e.printStackTrace();     }   } } 

Test the switch end

Package test; import java. io. IOException; import java. io. outputStream; import java.net. socket; import java. util. producer; import com. test. netty. message. header; import com. test. netty. message. message; public class ClientTest {public static void main (String [] args) {try {// connect to the server Socket socket = new Socket ("127.0.0.1", 8888 ); try {// DataOutputStream OutputStream out = socket. getOutputStream (); // enter the standard input stream for decoration. in); while (true) {String send = success. nextLine (); System. out. println ("client:" + send); byte [] by = send. getBytes ("UTF-8"); Header header = new Header (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, "713f17ca614361fb257dc6741332caf2",. length, 1); Message message = new Message (header, send); out. write (message. toByte (); out. flush (); // send the information obtained from the console to the server // out. writeUTF ("client:" + send); // read information from the server} finally {socket. close () ;}} catch (IOException e) {e. printStackTrace ();}}}

Test result, OK

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Related Article

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.