JAVA Netty 채 팅 방+채 팅 기능 구현 예시 코드

기능 소개
Netty 프레임 워 크 를 사용 하여 채 팅 방 기능 을 실현 하고 서버 는 클 라 이언 트 의 상하 한 상 태 를 감시 하고 메 시 지 를 전달 할 수 있 습 니 다.점 대 점 잡담 기능 도 동시에 실현 했다.기술 점 에서 나 는 모두 코드 에 비 고 를 했 는데,여 기 는 더 이상 반복 해서 쓰 지 않 는 다.netty 를 배우 고 싶 은 학생 들 에 게 참고 가 되 었 으 면 좋 겠 습 니 다.
서버 코드
서버 입구 코드

package nio.test.netty.groupChat;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

/**
 * netty       
 * @author zhang
 *
 */
public class NettyChatServer {
	private int port;
	
	public NettyChatServer(int port){
		this.port = port;
	}
	
	//    netty   
	private void init() throws Exception{
		EventLoopGroup boss = new NioEventLoopGroup(1);
		EventLoopGroup work = new NioEventLoopGroup(16);
		try {
			ServerBootstrap boot = new ServerBootstrap();
			boot.group(boss,work);
			boot.channel(NioServerSocketChannel.class);//  boss selector  channel     
			boot.option(ChannelOption.SO_BACKLOG, 128);//boss           
			boot.childOption(ChannelOption.SO_KEEPALIVE, true); //            
			boot.childHandler(new ChannelInitializer<SocketChannel>() {

				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					// channel   pipeline       Handler
					ChannelPipeline pipeline = ch.pipeline();
					pipeline.addLast("encoder",new StringEncoder());
					pipeline.addLast("decoder",new StringDecoder());
					pipeline.addLast(new ServerMessageHandler());//   Handler     
				}
			});
			System.out.println("       ...");
			//     
			ChannelFuture channelFuture = boot.bind(port).sync();
			channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() {

				@Override
				public void operationComplete(Future<? super Void> future)
						throws Exception {
					if(future.isSuccess()){
						System.out.println("       ...");
					}
					if(future.isDone()){
						System.out.println("       ...OK");
					}
					
				}
			});
			//  channel  
			channelFuture.channel().closeFuture().sync();
			channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() {

				@Override
				public void operationComplete(Future<? super Void> future)
						throws Exception {
					if(future.isCancelled()){
						System.out.println("       ..");
					}
					if(future.isCancellable()){
						System.out.println("       ..OK");
					}
					
				}
			});
			
		}finally{
			boss.shutdownGracefully();
			work.shutdownGracefully();
		}
	}
	/**
	 *       main   
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		new NettyChatServer(9090).init();

	}

}
서버 쪽 메시지 처리 Handler

package nio.test.netty.groupChat;

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;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
 *             Handler
 * @author zhang
 *
 */
public class ServerMessageHandler extends SimpleChannelInboundHandler<String>{
	/**
	 *      channel
	 * GlobalEventExecutor.INSTANCE        
	 *    channel    ChannelGroup        
	 *   channel          ,      
	 */
	private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
	/**
	 *         ,  key         ,
	 *            
	 *                            ChannelGroup       
	 */
	private static Map<String,Channel> all = new HashMap<String,Channel>();
	
	private SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	/**
	 *        
	 */
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, String msg)
			throws Exception {
		Channel channel = ctx.channel();
		/**
		 *                #      
		 */
		if(msg.contains("#")){
			String id = msg.split("#")[0];
			String body = msg.split("#")[1];
			Channel userChannel = all.get(id);
			String key = channel.remoteAddress().toString().split(":")[1];
			userChannel.writeAndFlush(sf.format(new Date())+"
【 】 "+key+" : "+body); return; } // for(Channel c : channels){ String addr = c.remoteAddress().toString(); if(channel !=c){ c.writeAndFlush(sf.format(new Date())+"
【 】 "+addr+" : "+msg); }else{ c.writeAndFlush(sf.format(new Date())+"
【 】 "+addr+" : "+msg); } } } /** * */ @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { Channel channel = ctx.channel(); String addr = channel.remoteAddress().toString(); /** * ChannelGroup channel * */ channels.writeAndFlush(sf.format(new Date())+"
【 】 "+addr+" "); channels.add(channel); String key = channel.remoteAddress().toString().split(":")[1]; all.put(key, channel); } /** * channel */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { String addr = ctx.channel().remoteAddress().toString(); System.out.println(sf.format(new Date())+"
【 】 "+addr+" "); } /** * channel */ @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { String addr = ctx.channel().remoteAddress().toString(); System.out.println(sf.format(new Date())+"
【 】 "+addr+" "); // String key = ctx.channel().remoteAddress().toString().split(":")[1]; all.remove(key); } /** * */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { //System.out.println(" !"); ctx.close(); } /** * * channel ChannelGroup */ @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { Channel channel = ctx.channel(); String addr = channel.remoteAddress().toString(); /** * ChannelGroup channel * */ channels.writeAndFlush(sf.format(new Date())+"
【 】 "+addr+" "); // ChannelGroup System.out.println(" :"+channels.size()); System.out.println("all:"+all.size()); } }
클 라 이언 트 메 인 방법 코드

package nio.test.netty.groupChat;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

import java.util.Scanner;

public class NettyChatClient {

	private String ip;
	
	private int port;
	
	public NettyChatClient(String ip,int port){
		this.ip = ip;
		this.port = port;
	}
	/**
	 *      
	 */
	private void init() throws Exception{
		//          
		EventLoopGroup work = new NioEventLoopGroup();
		try {
			Bootstrap boot = new Bootstrap();
			boot.group(work);
			boot.channel(NioSocketChannel.class);
			boot.handler(new ChannelInitializer<NioSocketChannel>() {

				@Override
				protected void initChannel(NioSocketChannel ch)
						throws Exception {
					ChannelPipeline pipeline = ch.pipeline();
					pipeline.addLast("encoder",new StringEncoder());
					pipeline.addLast("decoder",new StringDecoder());
					pipeline.addLast(new ClientMessageHandler());
					
				}
			});
			
			ChannelFuture channelFuture = boot.connect(ip, port).sync();
			channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() {

				@Override
				public void operationComplete(Future<? super Void> future)
						throws Exception {
					if(future.isSuccess()){
						System.out.println("      ...");
					}
					if(future.isDone()){
						System.out.println("       ...OK!");
					}
				}
			});
			System.out.println(channelFuture.channel().localAddress().toString());
			System.out.println("#################################################");
			System.out.println("~~~~~~~~~~~~~~   #    ~~              ~~~~~~~~~~~~~~~~~~");
			System.out.println("#################################################");
			
			/**
			 *           
			 */
			Channel channel = channelFuture.channel();
			//  channel
			Scanner scanner = new Scanner(System.in);
			while(scanner.hasNextLine()){
				String str = scanner.nextLine();
				channel.writeAndFlush(str+"
"); } channelFuture.channel().closeFuture().sync(); scanner.close(); } finally { work.shutdownGracefully(); } } /** * * @param args * @throws Exception */ public static void main(String[] args) throws Exception{ new NettyChatClient("127.0.0.1",9090).init(); } }
클 라 이언 트 메시지 처리 핸들 러

package nio.test.netty.groupChat;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
 *         Handler
 * @author zhang
 *
 */
public class ClientMessageHandler extends SimpleChannelInboundHandler<String> {

	/**
	 *        
	 */
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, String msg)
			throws Exception {
		System.out.println(msg);
		
	}
	/**
	 *        
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		ctx.close();
		
	}
}

테스트 결과
네 개의 클 라 이언 트 서버 엔 드 로 그 를 시작 하 였 습 니 다.효 과 는 다음 과 같 습 니 다.

클 라 이언 트 로그:

클 라 이언 트 2 로그:

클 라 이언 트 3 로그:

클 라 이언 트 4 로그:

현재 클 라 이언 트 4 에서 메 시 지 를 보 냅 니 다:

모든 클 라 이언 트 가 메 시 지 를 받 을 수 있 습 니 다:



연화 클 라 이언 트 클 라 이언 트 닫 기 3:
서버 로그:

다른 클 라 이언 트 로그:



비공개 메시지 발송:

이 클 라 이언 트 는 메 시 지 를 받 을 수 없습니다.


JAVA Netty 가 채 팅 방+개인 채 팅 기능 을 실현 하 는 예시 코드 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 JAVA Netty 채 팅 방 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 읽 어 주시 기 바 랍 니 다.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기