代码基于第二个例子,支持多客户端的连接,在线聊天。

主要思路:

  连接建立时,在服务器端,保存channel 对象,当有新的客户端加入时,遍历保存的channel集合,向其他客户端发送加入消息。

  当一个客户端发送消息时,在服务器端,遍历channel集合,判断是否为发送者,来修改发送内容,如:    XX说:  我说:

同样的:

server中的主程序和第二个例子类似

server中的initializer

 import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil; public class MyChatServerInitlalizer extends ChannelInitializer<SocketChannel> { @Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//解码器,根据分隔符来分割
pipeline.addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));//编码
pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));//解码 pipeline.addLast(new MyChatServerHandler()); }
}

server中的handler

 import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor; public class MyChatServerHandler extends SimpleChannelInboundHandler<String> { //这个对象可以获取到所有的channel
private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
} @Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
Channel channel = ctx.channel(); channelGroup.forEach(ch -> {
System.out.println("ii");
if(ch != channel) {
System.out.println("othor");
ch.writeAndFlush(channel.remoteAddress() + "发送的消息:" + msg + "\n");//发送消息出去的时候,这个\n,一定不能丢,不然发不出去
} else {
ch.writeAndFlush( "自己: " + msg + "\n");
}
}); //服务器接收到消息,相所有客户端 发送 消息
System.out.println("接收到 " + channel.remoteAddress() +" 客户端的消息:" + msg);
// //发送给其他客户端
// ctx.writeAndFlush("msg");
} @Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();//获取到连接
//告诉已有的其他连接
channelGroup.writeAndFlush("[服务器] - " + channel.remoteAddress() + " - 加入\n");
//再加入
channelGroup.add(channel);//把channel加到channelGroup
} @Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
channelGroup.writeAndFlush("[服务器] - " + channel.remoteAddress() + "已离开\n");
// channelGroup.remove(channel);//netty会自动将已经失去连接的channel,从channelGroup 中移除
} @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
System.out.println(channel.remoteAddress() + "上线了!");
} @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
System.out.println(channel.remoteAddress() + "下线了!");
}
}

clien中的主程序

 import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader; public class MyChatClient {
public static void main(String[] args) throws InterruptedException, IOException {
//客户端只需要一个
EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); try{ Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup)
.channel(NioSocketChannel.class)
.handler(new MyChatInitlaizer());
ChannelFuture channelFuture = bootstrap.connect("localhost", 8899).sync(); Channel channel = channelFuture.channel(); //channelFuture.channel().writeAndFlush("first msg");//发送数据,其实应该写到handler的active方法中 BufferedReader br = new BufferedReader(new InputStreamReader( System.in));
for (;;) {//死循环来接收客户端的输入
channel.writeAndFlush(br.readLine() + "\r\n");
} // channelFuture.channel().closeFuture().sync();
}finally {
eventLoopGroup.shutdownGracefully();
} }
}

client中的initializer和服务器端的类似

client中的handle,只要简单输出就行。

4、netty第三个例子,建立一个tcp的聊天的程序的更多相关文章

  1. j建立一个小的servlet小程序

    我们建立一个最简单的servlet程序,这个servelt程序只是单纯的输出helloworld. 步骤如下:如图:在Eclipse中选择新建一个项目,其中选择tomcat project然后点击下一 ...

  2. JMS学习(四)-一个简单的聊天应用程序分析

    一,介绍 本文介绍一个简单的聊天应用程序:生产者将消息发送到Topic上,然后由ActiveMQ将该消息Push给订阅了该Topic的消费者.示例程序来自于<JAVA 消息服务--第二版 Mar ...

  3. 用c写一个小的聊天室程序

    1.聊天室程序——客户端 客户端我也用了select进行I/O复用,同时监控是否有来自socket的消息和标准输入,近似可以完成对键盘的中断使用. 其中select的监控里,STDOUT和STDIN是 ...

  4. 利用JavaUDPSocket+多线程模拟实现一个简单的聊天室程序

    对Socket的一点个人理解:Socket原意是指插座.家家户户都有五花八门的家用电器,但它们共用统一制式的插座.这样做的好处就是将所有家用电器的通电方式统一化,不需要大费周章地在墙壁上凿洞并专门接电 ...

  5. web2py--------------用web2py写 django的例子 --------建立一个投票应用(3)

    我们建立了数据模型,然后这次来进行页面的展示 1.这里是列表页面的 control 这里是dal的语法 只有两行 第一行 是查询出所有问题,也就是问题的id大于0 第二行是返回问题的列表 这里是vie ...

  6. web2py--------------用web2py写 django的例子 --------建立一个投票应用(2)

    建立模型 我们在models下及那里polls.py 文件内容如下 # -*- coding: utf-8 -*- pollsdb=DAL(uri='sqlite://polls.db') polls ...

  7. web2py--------------用web2py写 django的例子 --------建立一个投票应用(1)

    按照上一篇我们新建一个名为  polls 的app 然后文件结构如下 然后web2py 会自动向里边添加一些代码. 我们需要剔除一些,如这个 controllers ,defualt.py  的ind ...

  8. TCP的三次握手(建立连接)和四次挥手(关闭连接)

    参照: http://course.ccniit.com/CSTD/Linux/reference/files/018.PDF http://hi.baidu.com/raycomer/item/94 ...

  9. TCP的三次握手(建立连接)与 四次挥手(关闭连接)

    一.TCP报文格式 TCP/IP协议的详细信息参看<TCP/IP协议详解>三卷本.下面是TCP报文格式图: TCP报文格式上图中有几个字段需要重点介绍下: (1)序号:Seq序号,占32位 ...

随机推荐

  1. 使用SQL计算宝宝每次吃奶的时间间隔

    需求:媳妇儿最近担心宝宝的吃奶时间不够规律,网上说是正常平均3小时喂奶一次,让我记录下每次的吃奶时间,分析下实际是否偏差很大,好在下次去医院复查时反馈给医生. 此外,还要注意有时候哭闹要吃奶,而实际只 ...

  2. Pandas学习(一)——数据的导入

    欢迎加入python学习交流群 667279387 学习笔记汇总 Pandas学习(一)–数据的导入 pandas学习(二)–双色球数据分析 pandas学习(三)–NAB球员薪资分析 pandas学 ...

  3. hdu2546

    Problem Description 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负) ...

  4. 【数据结构05】红-黑树基础----二叉搜索树(Binary Search Tree)

    目录 1.二分法引言 2.二叉搜索树定义 3.二叉搜索树的CRUD 4.二叉搜索树的两种极端情况 5.二叉搜索树总结 前言 在[算法04]树与二叉树中,已经介绍过了关于树的一些基本概念以及二叉树的前中 ...

  5. 【Selenium】自动进入网页,出现弹窗被卡住

    问题现象: 使用命令:driver.get("http://127.0.0.1/zentao/user-login.html") 进入网页,出现如下弹窗,无法进入 解决方法: #d ...

  6. Electron 设置 -webkit-app-region 后无法响应鼠标点击事件的解决方式

    参考博客:https://blog.csdn.net/qq_20264891/article/details/87721163

  7. Es6中箭头函数与普通函数的区别

    Es6中箭头函数与普通函数的区别? 普通function的声明在变量提升中是最高的,箭头函数没有函数提升 箭头函数没有属于自己的this,arguments 箭头函数不能作为构造函数,不能被new,没 ...

  8. static介绍、内部类、final、权限修饰符的作用范围

    static 关键字:(可用于修饰方法.变量)     static 特点:         static是静态修饰符,一般修饰成员变量.被static修饰的属于全局共享.被static修饰的成员属于 ...

  9. 《Java基础知识》Java IO流详解

    Java IO概念 1. 用于设备之间的数据传输. 2. Java 将操作数据流的功能封装到了IO包中. 3. 数据流流向分:输入流和输出流,操作对象为文件. 4. 流按照操作数据分:字节流(通用)和 ...

  10. SpringBoot电商项目实战 — 前后端分离后的优雅部署及Nginx部署实现

    在如今的SpringBoot微服务项目中,前后端分离已成为业界标准使用方式,通过使用nginx等代理方式有效的进行解耦,并且前后端分离会为以后的大型分布式架构.弹性计算架构.微服务架构.多端化服务(多 ...