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

主要思路:

  连接建立时,在服务器端,保存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. 使用 nginx 实现虚拟主机

    当多个系统需要部署的时候,有系统访问很小,为了节省成本,就需要将多个系统部署到同一台服务器上,怎么在同一台服务器上,完成不同系统的部署和访问,就需要使用虚拟主机实现. 使用端口实现虚拟主机 配置 ng ...

  2. 笔记||Python3之字典

    字典的定义与特性: 字典的每个键值key ==> value 对用冒号:分割,每个键值对之间用逗号分割,整个字典包括在花括号{}中. 字典名 = {键名1:值1, 键名2:值2} 如:dict ...

  3. 【MyBatis-Plus】使用学习

    [MyBatis-Plus]使用学习 ============================================== 1.插入和更新字段空和非空控制 2.插入和更新字段填充策略 ==== ...

  4. 【Maven】常用命令

    [Maven]常用命令 转载:https://www.cnblogs.com/yangchongxing/p/10267028.html Maven Jar 搜索:https://mvnreposit ...

  5. 2019年Spring核心知识点整理,看看你掌握了多少?

    前言 如今做Java尤其是web几乎是避免不了和Spring打交道了,但是Spring是这样的大而全,新鲜名词不断产生,学起来给人一种凌乱的感觉,在这里总结一下,理顺头绪. Spring 概述 Spr ...

  6. c#截取后台窗口的图片

    c#截取后台窗口的图片,自测可用,据说性能很一般,用用吧 struct RECT { public int Left; // x position of upper-left corner publi ...

  7. 深度强化学习(DQN-Deep Q Network)之应用-Flappy Bird

    深度强化学习(DQN-Deep Q Network)之应用-Flappy Bird 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-fu ...

  8. C# (转载)webbrowser专题(参考资料:https://www.cnblogs.com/blogpro/p/11458390.html)

    C# .Net 2.0实例学习:WebBrowser页面与WinForm交互技巧 2 Study Case :高亮显示 上一个例子中我们学会了查找文本——究跟到底,对Web页面还是只读不写.那么,如果 ...

  9. c++--语言本身

    c++ 面向对象概念(cout cin 类.对象 面向对象和面向过程求解问题) 易犯错误模型(引入成员函数的必要性) C语言和C++语言的关系 namespace 定义(嵌套).使用.标准命名空间st ...

  10. Nginx的配置文件位置以及组成部分结构讲解

    场景 Ubuntu Server 16.04 LTS上怎样安装下载安装Nginx并启动: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/detai ...