Netty 实现一对一客户端聊天(由服务器转发)

学习Netty有一个多星期,参考《Netty实战》敲了Echo C/S 代码,也学习了channelHandler等组件。不满足客户端服务器一对一聊天,所以寻思着自己实现一个客户端和客户端一对一聊天,消息由服务器转发。
如果有代码写的不合适的地方,还请评论指正。
《Netty实战》电子书下载地址

主要思路


服务器端

  1. 服务器端维护一个ChannelHandlerContext类型的数组,用来存储与服务器连接的各个channel的信息。 (思路来源于《Netty 实战》6.3.2)
  2. 最大连接数控制。设置一个变量为最大数,
  3. 服务器主动关闭连接。当检测到一个连接的客户端掉线或异常,服务器应主动关闭连接
  4. 服务器转发消息。通过ChannelHandlerContext类型的数组获得与之相连的channel信息,将服务器读到的消息写给另一个客户端
  5. 译码器解码器。使读写更加方便
  6. 为了便于调试,还附加了一些包含获取时间,服务器显示读取的消息等等函数

客户端

  1. 发送信息
  2. 读取信息
  3. 主动关闭连接
  4. 输入指定字符串时下线。由于是控制台程序,所以我设置输入“bye”或“再见”时,调用相关函数关闭连接

实现代码


服务器端

类结构

类名 说明
ServerHandler 继承ChannelInboundHandlerAdapter接口
Server 引导服务器端

实现代码

ServerHandler类

继承ChannelInboundHandlerAdapter接口,重写一些方法,添加一些私有变量来存储和控制channel信息

//ServerHandler类

import java.net.InetSocketAddress;
import java.util.Calendar;
import java.util.Vector;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

@Sharable   
public class ServerHandler extends ChannelInboundHandlerAdapter {
   

    private static final int MAX_CONN = 2;//指定最大连接数
    private int connectNum = 0;//当前连接数
    //channelHandlerContext表
    private Vector<ChannelHandlerContext> contexts = new Vector<>(2);

    //获取当前时间
    private String getTime() {

        Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int date = c.get(Calendar.DATE);
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        int second = c.get(Calendar.SECOND);
        return new String(year + "/" + month + "/" + date + " " + hour + ":" + minute + ":" + second);

    }

    /*
     * 重写channelActive()方法
     * 更新当前连接数
     * 控制连接客户端的个数,超过则关闭该channel
     * 更新contexts数组
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // TODO Auto-generated method stub
        connectNum++;
        //控制客户端连接数量,超过则关闭
        if (connectNum > MAX_CONN) {
            ctx.writeAndFlush(Unpooled.copiedBuffer("达到人数上限".getBytes()));
            ctx.channel().close();
            //当前连接数的更新放在channelInactive()里
        }
        //更新contexts
        contexts.add(ctx);
        //控制台输出相关信息
        InetSocketAddress socket = (InetSocketAddress) ctx.channel().remoteAddress();
        System.out.println(socket.getAddress().getHostAddress() + ":" + socket.getPort() + "已连接");
        System.out.println("当前连接数:" &#
  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值