📜 ⬆️ ⬇️

Development of a productive game server on Netty + Java

Piccy.info - Free Image Hosting

As promised, I provide a description of a productive game server on Netty, which I use in my projects.
Everything described below is not true in the last resort, but only the experience of using technologies in real projects.


')

Start over.



Our task is to make a game server.

What are the main tasks of the game server?
In short, then:

...

We will not consider working with the database and other things now. Focusing on the network part.

How can Netty help us in this?


Netty is a network library that will take over the direct work of sockets. Connect, disconnect clients. Reception, sending and fragmentation of packets. Those. netty will take care of all the low-level work with sockets.

How will netty help us?


Netty implements a very convenient architecture. For example, it allows you to connect multiple input data handlers. Those. in the first handler, we divide the incoming data stream into packets, and in the second we are already processing these packets. At the same time, you can flexibly manage the settings of the library itself, allocate the required number of threads or memory to it, etc ...
A common architecture with Netty might look like this:

Piccy.info - Free Image Hosting

We get 3 handlers:
1. Connection handler is a handler that is responsible for connecting / disconnecting clients. There will be checking the connectivity of clients (black, white lists, IP filters, etc.) as well as the correct disconnection of clients with the closure of all resources used.

2. Frame handler is a handler that divides the data stream into separate packets.
For convenience, we assume that the package consists of two parts. 1-header, which describes the length of the packet, and 2-directly data packet.

3. Packet handler is a game message handler. Here we will receive data from the packet and further process it.

Let's sort each part in the code.

Connection handler

public class ConnectionHandler extends SimpleChannelHandler
{

    @Override
    public void channelOpen( ChannelHandlerContext ctx, ChannelStateEvent e ) throws Exception
    {
        if(       )
        {
	//  
            e.getChannel().close();
        }
    }
    
    @Override
    public void channelClosed( ChannelHandlerContext ctx, ChannelStateEvent e ) throws Exception
    {
        // ,   ,        .
    }
  
    
    @Override
    public void exceptionCaught( ChannelHandlerContext ctx, ExceptionEvent e ) throws Exception
    {
	//   
        log.error( "message: {}", e.getCause().getMessage() );
    }    
    
}


Frame handler.

. , .
public class FrameHandler extends ReplayingDecoder<DecoderState>
{
    public enum DecoderState
    {
        READ_LENGTH,
        READ_CONTENT;
    }  

    private int length;

    public ProtocolPacketFramer()
    {
        super( DecoderState.READ_LENGTH );
    }
    
    @Override
    protected Object decode( ChannelHandlerContext chc, Channel chnl, ChannelBuffer cb, DecoderState state ) throws Exception
    {
        switch ( state )
        {
            case READ_LENGTH:
                length = cb.readInt();
                checkpoint( DecoderState.READ_CONTENT );
                
            case READ_CONTENT:
                ChannelBuffer frame = cb.readBytes( length );
                checkpoint( DecoderState.READ_LENGTH );
                return frame;
                
            default:
                throw new Error( "Shouldn't reach here." );
        }
    }
}


Packet handler

public class ProtocolPacketHandler extends SimpleChannelHandler
{
    @Override
    public void messageReceived( ChannelHandlerContext ctx, MessageEvent e ) throws Exception
    {
	//  
            byte[] msg = ((ChannelBuffer)e.getMessage()).array();
            
	//     
            Packet packet = new Packet();
            packet.setData( msg );
            packet.setSender( session );

	//      
            session.addReadPacketQueue( packet );

	//      
            Server.getReader().addSessionToProcess( session );
    }
}


, . Packet . .

. . , , . . 2 . TCP , . . , . .
, TCP ( Akka ) . . TCP Netty , .

.

Piccy.info - Free Image Hosting

. . TCP Netty . .

. Session , 2 , . Packet . Netty , . , . . . . … - )) , , .

.
Piccy.info - Free Image Hosting

.


public final class ReadQueueHandler implements Runnable
{
    private final BlockingQueue<Session> sessionQueue;
    private final ExecutorService        threadPool;
    private int                          threadPoolSize;
    
    public ReadQueueHandler( int threadPoolSize )
    {
        this.threadPoolSize = threadPoolSize;
        this.threadPool     = Executors.newFixedThreadPool( threadPoolSize );
        this.sessionQueue   = new LinkedBlockingQueue();
        
        initThreadPool();
    }
    
    private void initThreadPool()
    {
        for ( int i = 0; i < this.threadPoolSize; i++ )
        {
            this.threadPool.execute( this );
        }
    }
    
    //      
    public void addSessionToProcess( Session session )
    {
        if ( session != null )
        {
            this.sessionQueue.add( session );
        }
    }    
    
    @Override
    public void run()
    {
        while ( isActive )
        {
                //     
                Session session = (Session) this.sessionQueue.take();
                
                //     
                //  
                packet = session.getReadPacketQueue().take();

                //       
                data =  packet.getData();
        }
    }    
}


. . . TCP . . Netty . .

protobuf. . , )

, AMD 1.4 (lenovo edge 13), 18-20 . .

P.S. — .

Source: https://habr.com/ru/post/136765/


All Articles