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位 ...
随机推荐
- 纯手工搭建K8s(单节点)
准备说明: 因为为纯手动搭建,所以针对安装时需要的一些安装包需提前下载好 cfssl_linux-amd64. cfssljson_linux-amd64. cfssl-certinfo_linux- ...
- Spring Boot 外部化配置(一)- Environment、ConfigFileApplicationListener
目录 前言 1.起源 2.外部化配置的资源类型 3.外部化配置的核心 3.1 Environment 3.1.1.ConfigFileApplicationListener 3.1.2.关联 Spri ...
- ARTS-S cmake,googletest使用
编译gtest 下载指定tag的源代码 git clone https://github.com/google/googletest.git cd googletest git checkout ta ...
- 基于iCamera测试光电大赛官方指定摄像头mt9m001调试小结
基于iCamera测试光电大赛官方指定摄像头mt9m001调试小结 先看看官方的接口 组委会指定的模块接口 信号定义说明: VDD:3.3v GND:地 SCK:摄像头寄存器的iic配置信号的时钟线 ...
- Linq 常用操作(增删改)
增加 using(var db = new Entities()) { //数据操作 UserInfo user = new UserInfo() { UserName = "zhangsa ...
- Orleans[NET Core 3.1] 学习笔记(二)Hello World
项目结构 开始Orleans之前,我们都知道Orleans主要可以分为俩部分,Host和Client. 所以我们可以创建如下的项目结构: IGrain 一个包含Grain接口的库(.NET Stand ...
- 201871010119-帖佼佼《面向对象程序设计(java)》第二周学习总结
项目 内容 这个作业属于哪个课程 <任课教师博客主页链接> https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址> ...
- 一个非常美的FlutterUI组件扩展集:FLUI
项目地址 FLUI 官网 下载 Demo APK 体验 这是一个群内的网友写的,感觉里面的组件风格非常美,封装的挺到位的,在此推荐给大家,具体可以参考学习. 可以学到的知识还是挺多的,组件UI封装可以 ...
- 【译】在React中实现条件渲染的7种方法
原文地址:https://scotch.io/tutorials/7-ways-to-implement-conditional-rendering-in-react-applications 借助R ...
- 【SHOI 2007】善意的投票
Problem Description 幼儿园里有 \(n\) 个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己的主见,但是为了照顾 ...