基于netty的一个简单的时间服务器的实现(netty学习)

基本功能:与客户端建立连接后立刻发送当前时间

先建立一个时间的类

package timeExample;

import java.sql.Date;

public class UnixTime {

    private final long value;

    public UnixTime() {
        this(System.currentTimeMillis()/1000L);
    }

    public UnixTime(long value) {
        this.value = value;
    }

    public long value() {
        return value;
    }

    @Override
    public String toString() {
        return new Date((value())*1000L ).toString();

    }
    public static void main(String[] arg) {
        System.out.println(new UnixTime());
    }
}

服务端代码:

package timeExample;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

public class TimeEncoder extends MessageToByteEncoder<UnixTime> {

    @Override
    protected void encode(ChannelHandlerContext ctx, UnixTime msg, ByteBuf out) throws Exception {
        // TODO Auto-generated method stub
        out.writeInt((int)msg.value());
    }

}
/**
 *
 * 这个类同样可以这样实现:
 * public class TimeEncoder extends ChannelOutboundHandlerAdapter {
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
        UnixTime m = (UnixTime) msg;
        ByteBuf encoded = ctx.alloc().buffer(4);
        encoded.writeInt((int)m.value());
        ctx.write(encoded, promise); // (1)
    }
}
 * 可以看到MessageToByteEncoder这个类封装了一些必要且固定的代码
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 * **/
package timeExample;

import java.beans.EventHandler;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOutboundHandlerAdapter;

public class TImeServerHandler extends ChannelInboundHandlerAdapter{
    //之所以用ChannelActive是因为这个timeServer的作用是在连接建立后立刻给客户端发送时间,而不接收客户端发送的消息
    //channelActive() method will be invoked when a connection is established and ready to generate traffic
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ChannelFuture future=ctx.writeAndFlush(new UnixTime());
        //使用的是JavaNio,因此它是非阻塞的,writeAndFlush可能还未完成就返回结果,ChannelFuture是标志这个操作的状态
        //因此可以添加监听器监听这个操作状态
        future.addListener(ChannelFutureListener.CLOSE);//一旦监听听监听到操作完成就关闭连接。这个是下面那段代码的简写
      /*  future.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) {
                assert f == future;
                ctx.close();
            }
        }); */

    }

}
package timeExample;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.Future;
//without receiving any requests and closes the connection once the message is sent
//close the connection on completion.
public class TimeServer {
    public int port;
    public TimeServer(int port) {
        this.port=port;

    }
    public void run() throws InterruptedException {
        ServerBootstrap b=new ServerBootstrap();
        EventLoopGroup boss=new NioEventLoopGroup();
        EventLoopGroup worker= new NioEventLoopGroup();
        try {
        b.group(boss,worker).channel(NioServerSocketChannel.class)
        .childHandler(new ChannelInitializer<Channel>() {

            @Override
            protected void initChannel(Channel ch) throws Exception {
                ch.pipeline().addLast(new TimeEncoder(),new TImeServerHandler());// TODO Auto-generated method stub

            }
        }).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);
        ChannelFuture future=b.bind(port).sync();
        future.channel().closeFuture().sync();
    }
    finally {
        worker.shutdownGracefully();
        boss.shutdownGracefully();

    }
}
    public static void main(String arg[]) throws InterruptedException {
        new TimeServer(10111).run();
    }
}

客户端代码:

package timeExample;

import java.util.List;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
/**
 * netty将读到的消息缓存到一个buf里,有时候一个完整的消息就会被碎片化到不同的buf里了
 * 使用ByteToMessageDecoder来解决这个问题
 *
 * */
public class TimeDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // TODO Auto-generated method stub

        if(in.readableBytes()<4)
            return;//每当有新的data到来时decode()方法就会被调用
        UnixTime t=new UnixTime(in.readUnsignedInt());
        out.add(t);

    }

}
package timeExample;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPromise;

public class TimeClientHandler extends ChannelInboundHandlerAdapter{

	@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		UnixTime t=(UnixTime)msg;
        System.out.println(t);
        ctx.close();
    }

}
package timeExample;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class TimeClient {
    private String address;
    private int port;
    TimeClient(String address,int port){
        this.address=address;
        this.port=port;

    }
    public void run() throws InterruptedException {

        EventLoopGroup worker=new NioEventLoopGroup();
        Bootstrap b=new Bootstrap();
        try {
        b.group(worker).channel(NioSocketChannel.class).handler(new ChannelInitializer<Channel>() {

            @Override
            protected void initChannel(Channel ch) throws Exception {
                // TODO Auto-generated method stub
                ch.pipeline().addLast(new TimeDecoder(),new TimeClientHandler());

            }
        }).option(ChannelOption.SO_KEEPALIVE, true);
        ChannelFuture future =b.connect(address, port).sync();
        future.channel().closeFuture().sync();

    }finally {
        worker.shutdownGracefully();//当EventLoopGroup shutdown以后所有的Channel才会shutdown。
    }

    }
    public static void main(String[] arg) throws InterruptedException {
        new TimeClient("localhost",10111).run();
    }

}

参考:netty官方文档:Netty.docs: User guide for 4.x

原文地址:https://www.cnblogs.com/cai-cai777/p/10274389.html

时间: 2024-09-29 06:49:14

基于netty的一个简单的时间服务器的实现(netty学习)的相关文章

使用 Nodejs 搭建一个简单的Web服务器

使用Nodejs搭建Web服务器是学习Node.js比较全面的入门教程,因为要完成一个简单的Web服务器,你需要学习Nodejs中几个比较重要的模块,比如:http协议模块.文件系统.url解析模块.路径解析模块.以及301重定向问题,下面我们就简单讲一下如何来搭建一个简单的Web服务器. 作为一个Web服务器应具备以下几个功能: 1.能显示以.html/.htm结尾的Web页面 2.能直接打开以.js/.css/.json/.text结尾的文件内容 3.显示图片资源 4.自动下载以.apk/.

自己动手模拟开发一个简单的Web服务器

开篇:每当我们将开发好的ASP.NET网站部署到IIS服务器中,在浏览器正常浏览页面时,可曾想过Web服务器是怎么工作的,其原理是什么?“纸上得来终觉浅,绝知此事要躬行”,于是我们自己模拟一个简单的Web服务器来体会一下. 一.请求-处理-响应模型 1.1 基本过程介绍 每一个HTTP请求都会经历三个步凑:请求-处理-响应:每当我们在浏览器中输入一个URL时都会被封装为一个HTTP请求报文发送到Web服务器,而Web服务器则接收并解析HTTP请求报文,然后针对请求进行处理(返回指定的HTML页面

如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1

原文:http://www.raywenderlich.com/2941/how-to-write-a-simple-phpmysql-web-service-for-an-ios-app 作为一个iPhone/iPad开发者,能够自己写一个简单的web服务器将是很有用的. 例如,你可能希望在软件启动时显示一些来自服务器的更新,或者在服务器端保存一些用户数据.除了你的想象力,没有什么能限制你了. 在第一篇中,我们将会一步一步的建立一个web服务器,基于promo code system(促销码系

简介(1)-概述、一个简单的时间获取客户程序

1.概述 大多数网络应用划分:客户(client)和服务器(server) 一些复杂的网络应用:异步回调通信,即服务器向客户发起请求消息. 协议栈:应用协议.TCP协议.IP协议.以太网协议 局域网(local area network,LAN),广域网(wide area network,WAN). 路由器是广域网的架构设备. 因特网:当今最大的广域网. POSIX:一种被多数厂商采纳的标准. 2.一个简单的时间获取客户程序 1)创建套接字 socket函数 2)指定服务器的IP地址和端口 s

创建一个简单的 MDM 服务器(1)

前提:已获得 APNS 证书 ,已完成 MDM 配置描述文件的制作.请参考< MDM 证书申请流程 >一文和<配置MDM Provisioning Profile>. 环境:OSX 10.9.2,JDK 1.6,Eclipse JavaEE Helois,Tomcat 7.0 一.前言 <THE IOS MDMPROTOCOL>(即Inside Apple MDM)一文中描述了一个简单 MDM Server Python 实现(server.py).笔者也曾参照此文配置

【Python】 做一个简单的 http 服务器

# coding=utf-8 ''' Created on 2014年6月15日 @author: Yang ''' import socket import datetime # 初始化socket s = socket.socket() # 获取主机名, 也可以使用localhost # host = socket.gethostname() host = "localhost" # 默认的http协议端口号 port = 80 # 绑定服务器socket的ip和端口号 s.bin

java实现一个简单的Web服务器

Web服务器也称为超文本传输协议服务器,使用http与其客户端进行通信,基于java的web服务器会使用两个重要的类, java.net.Socket类和java.net.ServerSocket类,并基于发送http消息进行通信. 这个简单的Web服务器会有以下三个类: *HttpServer *Request *Response 应用程序的入口在HttpServer类中,main()方法创建一个HttpServer实例,然后调用其await()方法,顾名思义,await()方法会在指定端口

自己模拟的一个简单的web服务器

首先我为大家推荐一本书:How Tomcat Works.这本书讲的很详细的,虽然实际开发中我们并不会自己去写一个tomcat,但是对于了解Tomcat是如何工作的还是很有必要的. Servlet容器是如何工作的 servlet容器是一个复杂的系统.不过,一个servlet容器要为一个servlet的请求提供服务,基本上有三件事要做: 1,创建一个request对象并填充那些有可能被所引用的servlet使用的信息,如参数.头部. cookies.查询字符串. URI 等等.一个 request

通过python 构建一个简单的聊天服务器

构建一个 Python 聊天服务器 一个简单的聊天服务器 现在您已经了解了 Python 中基本的网络 API:接下来可以在一个简单的应用程序中应用这些知识了.在本节中,将构建一个简单的聊天服务器.使用 Telnet,客户机可以连接到 Python 聊天服务器上,并在全球范围内相互进行通信.提交到聊天服务器的消息可以由其他人进行查看(以及一些管理信息,例如客户机加入或离开聊天服务器).这个模型如图 1 所示. 图 1. 聊天服务器使用 select 方法来支持任意多个客户机 聊天服务器的一个重要