java-chat-room 聊天室基于Netty

Client (main()启动)

NettyClient.java

package com.example.server;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.util.Scanner;

/**
 * netty客户端 . 
* * @author hkb */
public class NettyClient { /** * 主机 */ private String host; /** * 端口号 */ private int port; /** * 客户端昵称 */ private String name = "client1"; private static String USER_EXIST = "system message: user exist, please change a name"; private static String USER_CONTENT_SPILIT = "#@#"; /** * 构造函数 * * @param host * @param port */ public NettyClient(String host, int port) { this.host = host; this.port = port; } /** * 连接方法 */ public void connect() { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.channel(NioSocketChannel.class); bootstrap.group(group); bootstrap.option(ChannelOption.TCP_NODELAY, true); // bootstrap.option(ChannelOption.SO_KEEPALIVE, true); bootstrap.handler(new NettyClientInitializer()); Channel channel = bootstrap.connect(host, port).sync().channel(); //在主线程中 从键盘读取数据输入到服务器端 Scanner scan = new Scanner(System.in); while (scan.hasNextLine()) { String line = scan.nextLine(); System.out.println( line); // 向服务端server 发送信息 channel.writeAndFlush(line + "\n"); // channel.closeFuture().sync(); } } catch (Exception e) { e.printStackTrace(); } finally { group.shutdownGracefully(); } } /** * 测试入口 * * @param args */ public static void main(String[] args) { String host = "127.0.0.1"; int port = 11111; NettyClient nettyClient = new NettyClient(host, port); nettyClient.connect(); } }

NettyClientHandler.java

package com.example.server;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

/**
 * 客户端处理器 . 
* * @author hkb */
public class NettyClientHandler extends SimpleChannelInboundHandler<String> { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println("收到服务端消息: " + msg); } }

NettyClientInitializer.java

package com.example.server;

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;

/**
 * 客户端初始化 . 
* * @author hkb */
public class NettyClientInitializer extends ChannelInitializer<SocketChannel> { /** * 初始化channel */ @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));//inbound pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast(new NettyClientHandler()); } }

Server (基于Springboot)

pom.xml

pom文件中添加如下依赖:包括netty及springboot的依赖

    
        org.springframework.boot
        spring-boot-starter-parent
        1.5.1.RELEASE
         
    
    
  
    
        
            io.netty
            netty-all
            4.1.0.Final
        
        
     
            org.springframework.boot
            spring-boot-configuration-processor
            true
        
        
        
            org.springframework.boot
            spring-boot-starter-redis
            ${spring-boot-starter-redis-version}
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
    

NettyServerListener.java

springboot 的服务监听器

package com.example.config;

import com.example.server.NettyServer;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 * netty服务监听器 . 
* * @author hkb */
@WebListener public class NettyServerListener implements ServletContextListener { /** * 注入NettyServer */ @Autowired private NettyServer nettyServer; @Override public void contextInitialized(ServletContextEvent sce) { Thread thread = new Thread(new NettyServerThread()); System.out.println("初始化 context"); // 启动netty服务 thread.start(); } @Override public void contextDestroyed(ServletContextEvent sce) { } /** * netty服务启动线程 .
* * @author hkb */
private class NettyServerThread implements Runnable { @Override public void run() { nettyServer.run(); } } }

NettyServer.java

package com.example.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import static org.junit.internal.Classes.getClass;

/**
 * netty服务端 . 
* * @author hkb */
@Component public class NettyServer { /** * 日志 */ private Logger log = LoggerFactory.getLogger(NettyServer.class); /** * 端口号 */ @Value("${netty.port}") private int port; /** * 启动服务器方法 * * @param */ public void run() { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup); serverBootstrap.channel(NioServerSocketChannel.class); serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024); serverBootstrap.handler(new LoggingHandler(LogLevel.INFO)); serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true); serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true); serverBootstrap.childHandler(new NettyServerInitializer()); // 绑定端口,开始接收进来的连接 ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); log.info("netty服务启动: [port:" + port + "]"); // 等待服务器socket关闭 channelFuture.channel().closeFuture().sync(); } catch (Exception e) { log.error("netty服务启动异常-" + e.getMessage()); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }

NettyServerHandler.java

package com.example.server;

import com.alibaba.fastjson.JSON;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.Map;

/**
 * 服务端处理器 . 
* * @author hkb */
public class NettyServerHandler extends SimpleChannelInboundHandler<String> { /** * 日志 */ private Logger log = LoggerFactory.getLogger(getClass()); @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) { StringBuilder sb = null; Map<String, Object> result = null; System.out.println(" 收到客户信息 :" + msg); try { // 报文解析处理 sb = new StringBuilder(); result.put("客户信息", msg); sb.append(result); sb.append("\n"); ctx.writeAndFlush(sb); } catch (Exception e) { String errorCode = "-1\n"; ctx.writeAndFlush(errorCode); log.error("报文解析失败: " + e.getMessage()); } } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); String clientIp = insocket.getAddress().getHostAddress(); log.info("收到客户端[ip:" + clientIp + "]连接"); // ctx.fireChannelActive(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // 当出现异常就关闭连接 ctx.close(); } }

NettyServerInitializer.java

package com.example.server;

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;

/**
 * 服务端初始化 . 
* * @author hkb */
public class NettyServerInitializer extends ChannelInitializer<SocketChannel> { /** * 初始化channel */ @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast(new NettyServerHandler()); } }

github源码:https://github.com/weiyang00/chat-rooms/tree/master/netty-chat-room

你可能感兴趣的:(Java)