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;
    }
}

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

时间: 2024-09-30 18:37:23

netty 3.9.2 UDP协议服务器和客户端DEMO的相关文章

python socket之tcp服务器与客户端demo

python socket之tcp服务器与客户端demo 作者:vpoet 日期:夏季 server: # -*- coding: cp936 -*- ''' 建立一个python server,监听指定端口, 如果该端口被远程连接访问,则获取远程连接,然后接收数据, 并且做出相应反馈. ''' import socket if __name__=="__main__": print "Server is starting" sock = socket.socket

Netty入门(二)时间服务器及客户端

在这个例子中,我在服务器和客户端连接被创立时发送一个消息,然后在客户端解析收到的消息并输出.并且,在这个项目中我使用 POJO 代替 ByteBuf 来作为传输对象. 一.服务器实现 1.  首先我们自定义传输数据对象 1 package com.coder.client; 2 3 import java.util.Date; 4 5 /** 6 * 自定义时间数据类 7 * @author Coder 8 * 9 */ 10 public class Time { 11 private fin

网络编程 UDP协议 TCP局域网客户端与服务端上传下载电影示例

UDP协议 (了解) 称之为数据包协议. 特点: 1) 不需要建立链接. 2) 不需要知道对方是否收到. 3) 数据不安全 4) 传输速度快 5)能支持并发 6) 不会粘包 7) 无需先启动服务端再启动客户端 优点: - 传输速度快 - 能支持并发 - 不会粘包 缺点: - 数据不安全, 容易丢失 应用场景: 早期的QQ聊天室. # server端 import socket # socket.SOCK_DGRAM ---> UPD协议 server = socket.socket(type=s

node.js中通过dgram数据报模块创建UDP服务器和客户端

node.js中 dgram 模块提供了udp数据包的socket实现,可以方便的创建udp服务器和客户端. 一.创建UDP服务器和客户端 服务端: const dgram = require('dgram'); //创建upd套接字 //参数一表示套接字类型,'udp4' 或 'udp6' //参数二表示事件监听函数,'message' 事件监听器 let server = dgram.createSocket('udp4'); //绑定端口和主机地址 server.bind(8888, '1

python编写socket服务器和客户端

本次使用的主要模块是socket模块,在这个模块中可以找到socket()函数,该函数用于创建套接字对象.套接字也有自己的方法集,这些方法可以实现基于套接字的网络通信. socket()模块函数 要创建套接字,必须使用socket.socket()函数,语法如下: socket(socket_family,socket_type,protocol=0) 其中socket_family是AF_UNIX(基于文件)或AF_INET(面向网络),socket_type是SOCK_STREAM(TCP)

时间获取程序服务器 UDP 协议无关

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie /** * UDP 协议无关 调用 getaddrinfo 和 udp_server **/ #include "unp.h" #include <time.h> int main(int argc, char **argv) { int sockfd; ssize_t n; char buff[MAXLINE]; time_t ticks; socklen_t le

python3实现UDP协议的简单服务器和客户端

利用python中的socket模块中的来实现UDP协议,这里写一个简单的服务器和客户端.为了说明网络编程中UDP的应用,这里就不写图形化了,在两台电脑上分别打开UDP的客户端和服务端就可以了. UDP:用户数据报协议,是一个面向无连接的协议.采用该协议不需要两个应用程序先建立连接.UDP协议不提供差错恢复,不能提供数据重传,因此该协议传输数据安全性差. 客户端 python3只能收发二进制数据,需要显式转码 from socket import * host = '192.168.48.128

Python全栈__服务器与多客户端通信、UDP协议、pycharm打印带颜色输出、时间同步的机制

1.服务器与多客户端通信 1 import socket 2 # 创建tcp socket的套接字 3 sk = socket.socket() 4 # bind 5 sk.bind(('127.0.0.1',8080)) 6 # 监听 7 sk.listen(5) 8 # 等待连接 9 while 1: 10 conn, addr = sk.accept() 11 while 1: 12 msg_s = input('>>>') 13 conn.send(msg_s.encode('u

Netty 系列九(支持UDP协议).

一.基础知识 UDP 协议相较于 TCP 协议的特点: 1.无连接协议,没有持久化连接:2.每个 UDP 数据报都是一个单独的传输单元:3.一定的数据报丢失:4.没有重传机制,也不管数据报是否可达:5.速度比TCP快很多,可用来高效处理大量数据 —— 牺牲了握手以及消息管理机制.6.常用于音频.视频场景,可以忍受一定的数据包丢失,追求速度上的提升. TCP 协议采用的是一种叫做单播的传输形式,UDP 协议提供了向多个接收者发送消息的额外传输形式(多播.广播): 单播(TCP 和 UDP):发送消