Java网络编程(8) - 怎么样使用NettyUDP协议通信?怎么样使用Netty的WebSocket通信案例?

Netty使用UDP协议通信案例

      UDP(User Datagram Protocol)即用户数据包协议,是OSI(Open Sysem Interconnection,开放式系统互联)模型的一种无连接的传输层协议,提供面向事务的简单不可靠信息传输服务。

      在网络中与TCP协议一样,用于处理数据包,是一种无连接信息,不关系数据包,只关注是否发出数据包,UDP有不提供数据包分组、组装,和不能对数据包进行排序的缺点。也就是说,当报文发送之后,是无法得知是否安全完整到达的。

      UDP用来支持那些需要在计算机之间传输数据的网络应用,比如视频会议系统在内的众多C/S模式的网络应用都需要使用UDP协议。

import io.netty.bootstrap.Bootstrap;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelHandlerContext;

import io.netty.channel.ChannelOption;

import io.netty.channel.EventLoopGroup;

import io.netty.channel.SimpleChannelInboundHandler;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.DatagramPacket;

import io.netty.channel.socket.nio.NioDatagramChannel;

import io.netty.util.CharsetUtil;

 

/**

 * Netty UDP协议-服务端

 */

public class N04UDPServer {

    public static void main(String[] args) throws Exception {

         //UDPTcp不同,不关心数据包是否达到目的地

         EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        

         //启动类

         Bootstrap bootstrap = new Bootstrap();

         bootstrap.group(eventLoopGroup) //绑定链接类

                      .channel(NioDatagramChannel.class) //模式

                      .option(ChannelOption.SO_BROADCAST, true) //广播

                      .handler(new UdpServerHandler()); //数据处理类

        

         //绑定端口

         ChannelFuture channelFuture = bootstrap.bind(1111).sync();

         channelFuture.channel().closeFuture().await();

        

         //关闭

         eventLoopGroup.shutdownGracefully();

    }

}

/**

 * 服务端数据处理

 */

class UdpServerHandler extends SimpleChannelInboundHandler {

 

    /*

     * 接收数据的处理

     */

    @Override

    protected void messageReceived(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {

         String data = packet.content().toString(CharsetUtil.UTF_8);

         System.out.println("服务端:接收到的数据 - " + data);

        

         //回传消息

         ctx.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("收到数据。",CharsetUtil.UTF_8),packet.sender()));

    }

   

    @Override

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

         cause.printStackTrace();

    }

}

import java.net.InetSocketAddress;

 

import io.netty.bootstrap.Bootstrap;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelHandlerContext;

import io.netty.channel.ChannelOption;

import io.netty.channel.EventLoopGroup;

import io.netty.channel.SimpleChannelInboundHandler;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.DatagramPacket;

import io.netty.channel.socket.nio.NioDatagramChannel;

import io.netty.util.CharsetUtil;

 

/**

 * Netty UDP协议-客户端

 */

public class N04UDPClient {

    public static void main(String[] args) throws Exception {

         //发数据

         EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        

         //启动类

         Bootstrap bootstrap = new Bootstrap();

         bootstrap.group(eventLoopGroup) //绑定

                      .channel(NioDatagramChannel.class) //模式

                      .option(ChannelOption.SO_BROADCAST, true) //广播

                      .handler(new UdpClientHandler()); //处理类

        

         //绑定广播

         ChannelFuture channelFuture = bootstrap.bind(0).sync();

        

         //写出端口和广播掩码地址

         channelFuture.channel().writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("你好啊", CharsetUtil.UTF_8),

                                                  new InetSocketAddress("255.255.255.255",1111))).sync();

        

         //关闭

         eventLoopGroup.shutdownGracefully();

    }

}

class UdpClientHandler extends SimpleChannelInboundHandler {

 

    @Override

    protected void messageReceived(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {

         String data = msg.content().toString(CharsetUtil.UTF_8);

         System.out.println(data);

    }

   

    @Override

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

         cause.printStackTrace();

    }

}

 

Netty使用WebSocket通信案例

      WebSocket将网络套接字引入到了客户端和服务端,众所周知,之前实现聊天功能,可能需要古老的Socket技术,或者是古老的DWR框架,反之Ajax技术,在有可能就是Comet服务器推技术,HT的WebSocket可以很轻松的进行聊天功能实现,Netty和H5的WebSocket结合非常的简单,Netty为我们封装了其协议类。

 

WebSocket特点

      单一的TCP链接,双方即可通信。

      对代理、防火墙和路由是透明的。

      无头部信息,Cookie和身份验证。

      无安全开销。

      通过ping/pong帧保持链路激活。

      服务器可主动传递消息给客户端,不在需要客户端轮询。

import java.util.Date;

 

import io.netty.bootstrap.ServerBootstrap;

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelFutureListener;

import io.netty.channel.ChannelHandlerContext;

import io.netty.channel.ChannelInitializer;

import io.netty.channel.EventLoopGroup;

import io.netty.channel.SimpleChannelInboundHandler;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.SocketChannel;

import io.netty.channel.socket.nio.NioServerSocketChannel;

import io.netty.handler.codec.http.DefaultFullHttpResponse;

import io.netty.handler.codec.http.FullHttpRequest;

import io.netty.handler.codec.http.HttpHeaderUtil;

import io.netty.handler.codec.http.HttpObjectAggregator;

import io.netty.handler.codec.http.HttpResponseStatus;

import io.netty.handler.codec.http.HttpServerCodec;

import io.netty.handler.codec.http.HttpVersion;

import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;

import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;

import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;

import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import io.netty.handler.codec.http.websocketx.WebSocketFrame;

import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;

import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;

import io.netty.util.CharsetUtil;

 

/**

 * WebSocket服务端

 */

public class N05WebSocketServer {

    public static void main(String[] args) throws Exception {

         //建立连接和传输数据

         EventLoopGroup connectEventLoopGroup = new NioEventLoopGroup();

         EventLoopGroup dataEventLoopGroup = new NioEventLoopGroup();

        

         //启动类

         ServerBootstrap serverBootstrap = new ServerBootstrap();

         serverBootstrap.group(connectEventLoopGroup, dataEventLoopGroup) //绑定

                          .channel(NioServerSocketChannel.class) //模式

                          .childHandler(new ChannelInitializer() {

                               @Override

                               protected void initChannel(SocketChannel ch) throws Exception {

                                   ch.pipeline().addLast("http-codec",new HttpServerCodec());

                                   ch.pipeline().addLast("aggregator",new HttpObjectAggregator(65535));

                                   ch.pipeline().addLast("handler",new WebSocketHandler()); //处理类

                               }

                          });

        

         //绑定端口

         ChannelFuture channelFuture = serverBootstrap.bind(1111).sync();

         channelFuture.channel().closeFuture().sync();

        

         //关闭

         connectEventLoopGroup.shutdownGracefully();

         dataEventLoopGroup.shutdownGracefully();

    }

}

class WebSocketHandler extends SimpleChannelInboundHandler {

 

    private WebSocketServerHandshaker serverHandshaker;

   

    @Override

    protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {

         //================= Http接入

        if(msg instanceof FullHttpRequest) {

             FullHttpRequest httpRequest = (FullHttpRequest) msg;

             //http-解码失败

             if(!httpRequest.decoderResult().isSuccess()

                      || (!"websocket".contentEquals(httpRequest.headers().get("Upgrade")))) {

                  //写出响应码

                  DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST);

                  ByteBuf byteBuf = Unpooled.copiedBuffer(response.status() + "",CharsetUtil.UTF_8);

                  response.content().writeBytes(byteBuf);

                  byteBuf.release();

                  HttpHeaderUtil.setContentLength(response, response.content().readableBytes());

                 

                  //如果是非Keep-Alive,关闭连接

                  ChannelFuture channelFuture = ctx.channel().writeAndFlush(response);

                  if(!HttpHeaderUtil.isKeepAlive(httpRequest) || response.status().code() != 200) {

                      channelFuture.addListener(ChannelFutureListener.CLOSE);

                  }

                  return ;

             }

            

             //构建握手响应返回

             WebSocketServerHandshakerFactory socketServerHandshakerFactory = new WebSocketServerHandshakerFactory("ws://localhost:8080/websocket", null, false);

             serverHandshaker = socketServerHandshakerFactory.newHandshaker(httpRequest);

             if(null == serverHandshaker) {

                  WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());

             }else {

                  serverHandshaker.handshake(ctx.channel(), httpRequest);

             }

        

         //================= WebSocket接入

         }else if(msg instanceof WebSocketFrame) {

             WebSocketFrame webSocketFrame = (WebSocketFrame) msg;

            

             //判断是否关闭链路的指令

             if(webSocketFrame instanceof CloseWebSocketFrame) {

                  serverHandshaker.close(ctx.channel(), (CloseWebSocketFrame) webSocketFrame.retain());

                  return ;

             }

            

             //是否是Ping

             if(webSocketFrame instanceof PingWebSocketFrame) {

                  ctx.channel().write(new PongWebSocketFrame(webSocketFrame.content().retain()));

                  return ;

             }

            

             //不支持二进制消息

             if(!(webSocketFrame instanceof TextWebSocketFrame)) {

                  throw new UnsupportedOperationException("不支持二进制消息");

             }

            

             //返回应答

             TextWebSocketFrame textWebSocketFrame = (TextWebSocketFrame) webSocketFrame;

             System.out.println("服务端:" + textWebSocketFrame.text());

            

             //写出

             ctx.channel().write(new TextWebSocketFrame(new Date().toString() + " - 欢迎"));

         }

    }

   

    @Override

    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

         ctx.flush();

    }

   

    @Override

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

         cause.printStackTrace();

    }

}

DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

Netty WebSocket 时间服务器

head>

<br>

<body>

<br>

<script type="text/javascript">

var socket;

if (!window.WebSocket)

{

    window.WebSocket = window.MozWebSocket;

}

if (window.WebSocket) {

    socket = new WebSocket("ws://localhost:1111/websocket");

    socket.onmessage = function(event) {

         var ta = document.getElementById('responseText');

         ta.value="";

         ta.value = event.data

    };

    socket.onopen = function(event) {

         var ta = document.getElementById('responseText');

         ta.value = "打开WebSocket服务正常,浏览器支持WebSocket!";

    };

    socket.onclose = function(event) {

         var ta = document.getElementById('responseText');

         ta.value = "";

         ta.value = "WebSocket 关闭!";

    };

} else {

    alert("抱歉,您的浏览器不支持WebSocket协议!");

}

 

function send(message) {

    if (!window.WebSocket) { return; }

    if (socket.readyState == WebSocket.OPEN) {

         socket.send(message);

    } else {

           alert("WebSocket连接没有建立成功!");

    }

}

script>

<form onsubmit="return false;">

<input type="text" name="message" value="Netty最佳实践"/>

<br><br>

<input type="button" value="发送WebSocket请求消息" onclick="send(this.form.message.value)"/>

<hr color="blue"/>

<h3>服务端返回的应答消息h3>

<textarea id="responseText" style="width:500px;height:300px;">textarea>

form>

body>

html>

 

你可能感兴趣的:(Java,NettyUDP协议通信,Netty,WebSocket,Netty的WebSocket,WebSocket怎么用,Netty的UDP通信)