4、netty第三个例子,建立一个tcp的聊天的程序
代码基于第二个例子,支持多客户端的连接,在线聊天。
主要思路:
连接建立时,在服务器端,保存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的聊天的程序的更多相关文章
- j建立一个小的servlet小程序
我们建立一个最简单的servlet程序,这个servelt程序只是单纯的输出helloworld. 步骤如下:如图:在Eclipse中选择新建一个项目,其中选择tomcat project然后点击下一 ...
- JMS学习(四)-一个简单的聊天应用程序分析
一,介绍 本文介绍一个简单的聊天应用程序:生产者将消息发送到Topic上,然后由ActiveMQ将该消息Push给订阅了该Topic的消费者.示例程序来自于<JAVA 消息服务--第二版 Mar ...
- 用c写一个小的聊天室程序
1.聊天室程序——客户端 客户端我也用了select进行I/O复用,同时监控是否有来自socket的消息和标准输入,近似可以完成对键盘的中断使用. 其中select的监控里,STDOUT和STDIN是 ...
- 利用JavaUDPSocket+多线程模拟实现一个简单的聊天室程序
对Socket的一点个人理解:Socket原意是指插座.家家户户都有五花八门的家用电器,但它们共用统一制式的插座.这样做的好处就是将所有家用电器的通电方式统一化,不需要大费周章地在墙壁上凿洞并专门接电 ...
- web2py--------------用web2py写 django的例子 --------建立一个投票应用(3)
我们建立了数据模型,然后这次来进行页面的展示 1.这里是列表页面的 control 这里是dal的语法 只有两行 第一行 是查询出所有问题,也就是问题的id大于0 第二行是返回问题的列表 这里是vie ...
- web2py--------------用web2py写 django的例子 --------建立一个投票应用(2)
建立模型 我们在models下及那里polls.py 文件内容如下 # -*- coding: utf-8 -*- pollsdb=DAL(uri='sqlite://polls.db') polls ...
- web2py--------------用web2py写 django的例子 --------建立一个投票应用(1)
按照上一篇我们新建一个名为 polls 的app 然后文件结构如下 然后web2py 会自动向里边添加一些代码. 我们需要剔除一些,如这个 controllers ,defualt.py 的ind ...
- TCP的三次握手(建立连接)和四次挥手(关闭连接)
参照: http://course.ccniit.com/CSTD/Linux/reference/files/018.PDF http://hi.baidu.com/raycomer/item/94 ...
- TCP的三次握手(建立连接)与 四次挥手(关闭连接)
一.TCP报文格式 TCP/IP协议的详细信息参看<TCP/IP协议详解>三卷本.下面是TCP报文格式图: TCP报文格式上图中有几个字段需要重点介绍下: (1)序号:Seq序号,占32位 ...
随机推荐
- 【Elasticsearch 7 探索之路】(五)搜索相关 Search-API
本节主要讲解 Elasticsearch 的 搜索相关功能 Search-API,讲解什么是 URL Search 和 Request Body Search 的语法,对常用的语法都会一一进行详细介绍 ...
- 常用的iOS第三方资源
一:第三方插件 1:基于响应式编程思想的oc 地址:https://github.com/ReactiveCocoa/ReactiveCocoa pod 'ReactiveCocoa', '~> ...
- 去除npm run dev日志warn记录
目录 一 babel的一些eslint方法废除了 问题 解决方案 相关文档 二 webpack的loaderUtils.parseQuery()被废弃了 问题 解决方案 相关文档 三 postcss相 ...
- git 使用详解(7)-- 远程仓库的使用
要参与任何一个 Git 项目的协作,必须要了解该如何管理远程仓库.远程仓库是指 托管在网络上 的项目仓库,可能会有好多个,其中有些你 只能读,另外有些可以写.同他人协作开发某个项目时,需要管理这些远程 ...
- linux gre隧道创建
目录 linux gre隧道创建 实验环境 实验目的 实验步骤 1.在host A(10.10.10.47)上面操作 2.在host B(192.168.0.118)上面操作 实验结果 还原实验环境 ...
- 🔥🔥🔥Spring Cloud进阶篇之Eureka原理分析
前言 之前写了几篇Spring Cloud的小白教程,相信看过的朋友对Spring Cloud中的一些应用有了简单的了解,写小白篇的目的就是为初学者建立一个基本概念,让初学者在学习的道路上建立一定的基 ...
- 笔记||Python3之对象的方法
什么是对象的方法? python中的一切类型的数据都是对象. 对象:数据和方法 对象数据:如 a = 'sfd' 对象方法:其实就是属于该对象的函数 对象的方法调用:对象.方法 字符串对象常用的方法: ...
- 深入理解 Java 方法
方法(有的人喜欢叫函数)是一段可重用的代码段.
- Sqlite 的管理工具SQLite
SQLite 的管理工具 SQLite Administrator 下载链接 : https://sqliteadmin.orbmu2k.de/ 下载后是一个免安装的程序文件,直接运行就可以了,可以选 ...
- vivado三人表决仿真
概述 下面以三人表决电路的verilog仿真来了解一下vivado软件的使用. 编写设计文件 首先可以在开始的界面通过create new project来新建工程,也可以通过file-->pr ...