• netty 3.9.2 UDP协议服务器和客户端DEMO


    说明:基于netty 3.9.2的udp协议实现的(如果你使用的版本是4.X或5.X,请参考其他方法);程序的逻辑结构是,客户端发送给服务端一串数据,服务器端返回给客户端“A”。在进行游戏开发时需要对udp的丢包进行处理,可以利用服务器端的返回值进行相关处理,以确定是否重发,这方面具体没有实现。

    文章结构:

    一、服务器端

    1、UDPServer

    2、UdpChannelPipelineFactory

    3、UDPServerHandler

    二、客户端

    1、UDPClient

    2、UDPClientChannelPipelineFactory

    3、UDPClientHandler

    三、ScanGetPort获取一个可用的端口号

    一、服务器端

    1、UDPServer

    初始化一个ConnectionlessBootstrap,setPipelineFactory,绑定一个端口号。ScanGetPort是一个工具类就是,获取一个可用的端口号,源代码在最后面贴出。

    package com.ls.udp.server;
    
    import java.net.InetSocketAddress;
    import java.util.concurrent.Executors;
    
    import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
    import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
    
    import com.andy.server.util.ScanGetPort;
    
    public class UDPServer {
        
        public final int PORT;
        public UDPServer(int port){
            PORT=port;
        }
        private ConnectionlessBootstrap  bootstrap;
        void start(){
            //init the bootstrap
            bootstrap=new ConnectionlessBootstrap(new NioDatagramChannelFactory(Executors.newCachedThreadPool()));
            bootstrap.setPipelineFactory(new UdpChannelPipelineFactory());
            bootstrap.bind(new InetSocketAddress(PORT));
            System.out.println("server start at:"+":"+PORT);
        }
        
        public static void main(String[] args) {
            /*
             * 获取一个可用的端口号
             */
            int port= new ScanGetPort().getPot(8080);
            new UDPServer(port).start();
        }
        
    }

    2、UdpChannelPipelineFactory

    注册一个handler

    package com.ls.udp.server;
    
    import org.jboss.netty.channel.ChannelPipeline;
    import org.jboss.netty.channel.ChannelPipelineFactory;
    import org.jboss.netty.channel.Channels;
    
    public class UdpChannelPipelineFactory implements ChannelPipelineFactory{
        
        /**
         * set the channel pipeline
         * 
         */
        @Override
        public ChannelPipeline getPipeline() throws Exception {
            ChannelPipeline pipeline = Channels.pipeline();
            pipeline.addLast("handler", new UDPServerHandler());
            return pipeline;
        }
    }

    3、UDPServerHandler

    handler类

    package com.ls.udp.server;
    
    import org.jboss.netty.buffer.ChannelBuffer;
    import org.jboss.netty.buffer.DynamicChannelBuffer;
    import org.jboss.netty.channel.ChannelHandlerContext;
    import org.jboss.netty.channel.ExceptionEvent;
    import org.jboss.netty.channel.MessageEvent;
    import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
    
    public class UDPServerHandler extends SimpleChannelUpstreamHandler{
    
        /**
         *  对于ChannelHandler,
         *  是UDP与TCP区别的核心所在。
         *  大家都知道UDP是无连接的,
         *  也就是说你通过 MessageEvent 参数对象的 getChannel() 方法获取当前会话连接,
         *  但是其 isConnected() 永远都返回 false。
         *  UDP 开发中在消息获取事件回调方法中,
         *  获取了当前会话连接 channel 对象后可直接通过 channel 的 write 方法发送数据给对端 channel.write(message, remoteAddress),
         *  第一个参数仍然是要发送的消息对象, 
         *  第二个参数则是要发送的对端 SocketAddress 地址对象。
         *  这里最需要注意的一点是SocketAddress,在TCP通信中我们可以通过channel.getRemoteAddress()获得,
         *  但在UDP通信中,我们必须从MessageEvent中通过调用getRemoteAddress()方法获得对端的SocketAddress 地址。 
         */
        @Override
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
                throws Exception {
            
            ChannelBuffer buffer = (ChannelBuffer)e.getMessage();
            byte[] recByte=buffer.copy().toByteBuffer().array();
            
            String msg=new String(recByte);
            System.out.println("from client:"+msg);
            
            ChannelBuffer responseBuffer= new DynamicChannelBuffer(1);
            
            responseBuffer.writeBytes("A".getBytes());
            
            //write to the client
            e.getChannel().write(responseBuffer, e.getRemoteAddress());
            
            
            super.messageReceived(ctx, e);
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
                throws Exception {
            super.exceptionCaught(ctx, e);
        }
    
    }

    二、客户端

    (基本结构和服务器端很像,不再赘述)

    1、UDPClient

    package com.ls.udp.client;
    
    import java.net.InetSocketAddress;
    import java.util.Scanner;
    
    import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
    import org.jboss.netty.buffer.ChannelBuffer;
    import org.jboss.netty.buffer.DynamicChannelBuffer;
    import org.jboss.netty.channel.Channel;
    import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
    
    public class UDPClient {
    
        private ConnectionlessBootstrap  bootstrap;
        private Channel channel;
        public void start(){
            //init the bootstrap
            bootstrap=new ConnectionlessBootstrap(new NioDatagramChannelFactory());
            bootstrap.setPipelineFactory(new UDPClientChannelPipelineFactory());
            bootstrap.setOption("localAddress", new InetSocketAddress(10001));
            channel=bootstrap.bind();
        }
        
        public void writebytes(byte[] bt,InetSocketAddress isa){
            if(bootstrap==null){
                this.start();
            }
            ChannelBuffer responseBuffer= new DynamicChannelBuffer(12);
            
            responseBuffer.writeBytes(bt);
            channel.write(responseBuffer, isa);
        }
        
        
        public static void main(String[] args) {
            
            
            UDPClient uClient=new UDPClient();
            
            
            Scanner scanner=new Scanner(System.in);
            String lienString=scanner.nextLine();
            while(!lienString.equals("bye")){
                
                uClient.writebytes(lienString.getBytes(), new InetSocketAddress("192.168.1.107",8080));
                lienString=scanner.nextLine();
            }
        }
        
        
    }

    2、UDPClientChannelPipelineFactory

    package com.ls.udp.client;
    
    import org.jboss.netty.channel.ChannelPipeline;
    import org.jboss.netty.channel.ChannelPipelineFactory;
    import org.jboss.netty.channel.Channels;
    public class UDPClientChannelPipelineFactory implements ChannelPipelineFactory{
        
        /**
         * set the channel pipeline
         * 
         */
        @Override
        public ChannelPipeline getPipeline() throws Exception {
            ChannelPipeline pipeline = Channels.pipeline();
            pipeline.addLast("handler", new UDPClientHandler());
            return pipeline;
        }
    }

    3、UDPClientHandler

    package com.ls.udp.client;
    
    import org.jboss.netty.buffer.ChannelBuffer;
    import org.jboss.netty.channel.ChannelHandlerContext;
    import org.jboss.netty.channel.ExceptionEvent;
    import org.jboss.netty.channel.MessageEvent;
    import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
    
    public class UDPClientHandler extends SimpleChannelUpstreamHandler{
    
        @Override
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
                throws Exception {
            
            
    
            ChannelBuffer buffer = (ChannelBuffer)e.getMessage();
            byte[] recByte=buffer.copy().toByteBuffer().array();
            
            String msg=new String(recByte);
            System.out.println("from server:"+msg);
            
            
            super.messageReceived(ctx, e);
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
                throws Exception {
            super.exceptionCaught(ctx, e);
        }
        
    }

    三、ScanGetPort获取一个可用的端口号

    package com.andy.server.util;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    /**
     * get the port
     * @author red
     *
     */
    public class ScanGetPort {
        public synchronized  int  getPot(int first){
            for(int i=first;i<65535;++i){
                ServerSocket ss=null;
                try {
                     ss= new ServerSocket(i);
                } catch (IOException e) {
                    //e.printStackTrace();
                }finally{
                    if(ss!=null){
                        if(ss.isBound()){
                            try {
                                ss.close();
                                System.out.println(i);
                                return i;
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            
                        }
                    }
                }
            }
            return -1;
        }
    }
  • 相关阅读:
    [转] 关于hibernate的缓存使用
    周鸿祎,我的互联网方法论
    cwRsync window下的跨服务器的文件同步
    一个代价11万的bug
    批处理备份
    NodeJs环境部署
    spring接收参数
    @Autowired
    谈谈把网站迁移到阿里云的一些感想和其中遇到的一些问题
    HTML5+JS 《五子飞》游戏实现(一)规则
  • 原文地址:https://www.cnblogs.com/redlight/p/3863361.html
Copyright © 2020-2023  润新知