fengshantao 2018-12-04
最近学习服务器开放,实现客户端(APP)与硬件设备之间的通信,我一想到socket,经过查询资料发现socket实现起来非常麻烦,同时也发现一个比较好的框架netty,觉得很不错,就开始尝试用他来撸一个点对点聊天系统,想了解的小伙伴可以自行去学习一下netty
一、一开始是导包,我是导入这三个包
二、开启服务器,话不多说直接上代码,比较代码很简单
DiscardServer.java 主函数开启服务
public class DiscardServer implements Runnable{
private int port;
private DiscardServer(int port) {
this.port = port;
}
public void run() {
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) // (3)
.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DiscardServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128) // (5)
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
// Bind and start to accept incoming connections.
Channel f = b.bind(port).sync().channel(); // (7)
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 1001;
}
new Thread( new DiscardServer(port)).start();
}
}
DiscardServerHandler.java 负责通信和消息处理
public class DiscardServerHandler extends ChannelInboundHandlerAdapter { // (1)
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) { // (2)
ByteBuf in = (ByteBuf) msg;
System.out.print(in.toString(io.netty.util.CharsetUtil.US_ASCII));
// 以静默方式丢弃接收的数据
// ((ByteBuf) msg).release(); // (3)
// ctx.writeAndFlush(firstMSG);
// String name=in.toString(io.netty.util.CharsetUtil.US_ASCII);
ApplicationContext.dealMessage(in.toString(io.netty.util.CharsetUtil.US_ASCII),ctx);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ApplicationContext.writeMessage("ni hao a",ctx);
System.out.println("this"+ctx.channel().remoteAddress().toString());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
// 出现异常时关闭连接。
cause.printStackTrace();
ctx.close();
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
super.channelWritabilityChanged(ctx);
}
}
ApplicationContext.java 负责客户端存储,消息协议制度和处理,定义Map来存储用户ID和客户端
public class ApplicationContext {
private static Map<Integer, ChannelHandlerContext> onlineUsers = new HashMap<Integer, ChannelHandlerContext>();//存储用户客户端消息
private static void add(Integer uid, ChannelHandlerContext ctx) {
onlineUsers.put(uid, ctx);
}
public static void remove(Integer uid) {
onlineUsers.remove(uid);
}
private static ChannelHandlerContext getContext(Integer uid) {
return onlineUsers.get(uid);
}
/**
* 消息处理、自定义协议
* @param message 消息
* @param ctx 客户端
*/
static void dealMessage(String message, ChannelHandlerContext ctx) {
String[] strings = message.split("#");
System.out.println(strings.length+" length");
//定义协议#号隔开数组下标0:数据类型、1:接收端用户ID、2:发送端ID、3内容
if (strings.length != 4)
return;
switch (strings[0]) {
case "0"://认证客户端
add(Integer.valueOf(strings[2]), ctx);
break;
case "2"://指定用户发送
ChannelHandlerContext ctxTwo = getContext(Integer.valueOf(strings[1]));
if (ctxTwo != null)
writeMessage(message,ctxTwo);
else
writeMessage("is get out",ctx);
break;
}
}
/**
* 发送消息
* @param message 消息
* @param ctx 客户端
*/
static void writeMessage(String message, ChannelHandlerContext ctx) {
ctx.writeAndFlush(Unpooled.buffer(message.getBytes().length).writeBytes(message.getBytes()));
}
}
接下来就大功告成了
三、调试方式
连接服务器,收到服务器返回(ni hao a)的消息, 马上返回消息绑定客户端如0#1#2#3,及表示自己客户端的id为2,其他客户端可通过id来向自己发送消息,发送消息给其他客户端如2#1#2#4,给id为1的客户端发送消息4。
上面那个只是我简单设置的一个协议,大家使用可以的话可以设置其他的协议或者数据格式json、XML等等
---------------------
作者:Andream778
来源:CSDN
原文:https://blog.csdn.net/qq_36480491/article/details/84711553
版权声明:本文为博主原创文章,转载请附上博文链接!