UDP unicast

A diferencia del TCP, en protocolos sin conexión como UDP, no existe una conexión persistente, y cada mensaje (un datagrama UDP) es una unidad de transmisión separada. Además, UDP tampoco tiene un mecanismo de corrección de errores TCP.


Por analogía, una conexión TCP es como hacer una llamada telefónica, en la que una serie de mensajes ordenados fluirán en ambas direcciones. En contraste, UDP es similar a poner una pila de postales en un buzón. No puede saber en qué orden llegarán a su destino, o si todos pueden llegar a su destino.


Estos aspectos de UDP pueden hacerle sentir serias limitaciones, pero también explican por qué es mucho más rápido que TCP: se ha eliminado toda la sobrecarga del mecanismo de administración de mensajes y apretón de manos. Obviamente, UDP es adecuado para aplicaciones que pueden manejar o tolerar la pérdida de mensajes, pero puede no ser adecuado para aplicaciones que manejan transacciones financieras.


Como un protocolo de transmisión sin conexión y poco confiable (adecuado para enviar paquetes de datos pequeños con frecuencia), no combinará ni enviará paquetes de datos (es decir, no hay un algoritmo de Nagle), envía datos directamente en un extremo, directamente Se envió, ya que no fusionará los datos, cada paquete de datos está completo (datos + encabezado UDP + encabezado IP, etc., una vez que los datos se encapsulan una vez), por lo que no hay un paquete fijo.


Aquí primero echamos un vistazo a UDP unicast,El modo de transmisión de unidifusión se define como el envío de un mensaje a un único destino de red identificado por una dirección única. Tanto los protocolos orientados a la conexión como los protocolos sin conexión son compatibles con este modelo.



A continuación, echemos un vistazo al ejemplo de unidifusión UDP. De hecho, hemos introducido la implementación de UDP en TCP y UDP en la programación de red . Aquí veamos cómo se implementa Netty. Primero, veamos primero Echa un vistazo al código del remitente

public class UdpSend {

    public static void main(String[] args) throws Exception {
        UdpSend udpSend = new UdpSend();
        udpSend.start("127.0.0.1", 8888);
    }

    private void start(String host, int port) throws Exception{
        EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.group(group)
                    .channel(NioDatagramChannel.class)
                    .handler(new UdpSendHandler());

            Channel channel = bootstrap.bind(0).sync().channel();
            channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("Hello Netty", CharsetUtil.UTF_8),
                    new InetSocketAddress(host, port)));

            if(!channel.closeFuture().await(10*1000)){
                System.out.println("消息发送超时");
            }
        } finally {
            group.shutdownGracefully();
        }
    }
}

De hecho, el cambio no es grande, enviamos directamente un dato al iniciar el puerto de envío, por supuesto, también podemos enviar datos en el método channelActive de la implementación de UdpSendHandler

public class UdpSendHandler extends SimpleChannelInboundHandler<DatagramPacket>{

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
        String data = msg.content().toString(CharsetUtil.UTF_8);
        System.out.println("收到响应信息:" + data);
        ctx.close();
    }
}

Entonces es el código de su extremo receptor, de la siguiente manera:

public class UdpReceive {

    public static void main(String[] args) throws Exception {
        UdpReceive udpReceive = new UdpReceive();
        udpReceive.start(8888);
    }

    private void start(int port) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.group(group)
                    .channel(NioDatagramChannel.class)
                    .handler(new UdpReceiveHandler());

            ChannelFuture channelFuture1 = bootstrap.bind(port).sync();
            channelFuture1.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}
public class UdpReceiveHandler extends SimpleChannelInboundHandler<DatagramPacket> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
        String data = msg.content().toString(CharsetUtil.UTF_8);
        System.out.println("收到请求信息:" + data);

        ctx.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("已成功收到该信息", CharsetUtil.UTF_8),
                msg.sender()));
    }
}

Los resultados son los siguientes:
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí



En el código anterior, usamos la clase DatagramPacket , que hereda DefaultAddressedEnvelope y usa ByteBuf como el contenedor de datos del mensaje.
Inserte la descripción de la imagen aquí
Los métodos comunes son los siguientes:

  • content (): para obtener el contenido del mensaje
  • remitente (): para obtener la información del remitente
  • destinatario (): para obtener la información del destinatario

En resumen, el DatagramPacket de Netty es un simple contenedor de mensajes que la implementación de DatagramChannel usa para comunicarse con nodos remotos. Similar a la postal en nuestra analogía anterior, contiene la dirección del receptor (y el remitente opcional) y la carga útil del mensaje en sí.

286 artículos originales publicados · Me gusta12 · Visitantes 10,000+

Supongo que te gusta

Origin blog.csdn.net/newbie0107/article/details/104452129
Recomendado
Clasificación