Netty 简易聊天 (一)

package com.ashuo.nettychat.server;

import com.ashuo.nettychat.server.handler.HttpHandler;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;

public class ChatServer {
	private int port = 80;
	public void start() {
		//boss线程
		EventLoopGroup boosGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		
		try {
			//链路配置引擎
			ServerBootstrap b = new ServerBootstrap();
			//主从模型
			b.group(boosGroup, workerGroup).channel(NioServerSocketChannel.class)
			.option(ChannelOption.SO_BACKLOG,1024)
			.childHandler(new ChannelInitializer<SocketChannel>() {

				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					// 子线程业务 
					
					//解码和编码 Http请求
					ch.pipeline().addLast(new HttpServerCodec());
					ch.pipeline().addLast(new HttpObjectAggregator(64*1024));
					//用于处理文件流
					ch.pipeline().addLast(new ChunkedWriteHandler());
					ch.pipeline().addLast(new HttpHandler());
					
				}
			});
			//阻塞 等待客户连接
			ChannelFuture f  = b.bind(this.port).sync();
			System.out.println("服务已经启动,监听端口是:"+this.port);
			f.channel().closeFuture().sync();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			workerGroup.shutdownGracefully();
			boosGroup.shutdownGracefully();
			
		}
	}
	public static void main(String[] args) {
		try {
			new ChatServer().start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
package com.ashuo.nettychat.server.handler;

import java.io.File;
import java.io.RandomAccessFile;
import java.net.URISyntaxException;
import java.net.URL;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.DefaultFileRegion;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.LastHttpContent;

public class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest>{
	
	private URL baseURL = HttpHandler.class.getProtectionDomain().getCodeSource().getLocation();
	private final String WEB_ROOT = "webroot";
	private File GetFileFromRoot(String fileName) throws URISyntaxException {
		String path = baseURL.toURI()+WEB_ROOT+"/"+fileName;
		path = !path.contains("file:")?path:path.substring(6);
		path = path.replaceAll("//", "/");	
		return new File(path);
	}
	@Override
	//netty 以0结尾的方法都是实现类的方法。Spring 以do 开头的都是实现类的方法
	protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
		// 客户端请求的url
		String uri = request.getUri();
		String page = uri.equals("/")?"index.html":uri;
		RandomAccessFile file =new RandomAccessFile(GetFileFromRoot(page), "r");
		String contentType = "text/html;";
		//不同的文件返回不懂的头
		if(uri.endsWith(".css")) {
			contentType = "text/css;";
		}else if (uri.endsWith(".js")) {
			contentType = "text/javascript;";
		}else if(uri.toLowerCase().matches("(jpg|png|gif)$")){
			String ext = uri.substring(uri.lastIndexOf("."));
			contentType="image/"+ext+";";
		}
		
		HttpResponse response = new DefaultHttpResponse(request.getProtocolVersion(), HttpResponseStatus.OK);
		response.headers().set(HttpHeaders.Names.CONTENT_TYPE,contentType+"charset=utf-8");
		boolean keepAlive = HttpHeaders.isKeepAlive(request);
		//长连接处理
		if(keepAlive) {
			response.headers().set(HttpHeaders.Names.CONTENT_LENGTH,file.length());
			response.headers().set(HttpHeaders.Names.CONNECTION,HttpHeaders.Values.KEEP_ALIVE);
		}
		
		ctx.write(response);
		ctx.write(new DefaultFileRegion(file.getChannel(), 0, file.length()));
		
		//清空缓冲区(不要忘)(不要忘)(不要忘)
		ChannelFuture f =ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
		if(!keepAlive) {
			f.addListener(ChannelFutureListener.CLOSE);
		}
//		System.out.println(file);
		
	}

}

pom

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.ashuo</groupId>
	<artifactId>nettychat</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>nettychat</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>io.netty</groupId>
			<artifactId>netty-all</artifactId>
			<version>4.1.6.Final</version>
		</dependency>
		<dependency>
			<groupId>org.msgpack</groupId>
			<artifactId>msgpack</artifactId>
			<version>0.6.12</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.4</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

猜你喜欢

转载自blog.csdn.net/ASZJBGD/article/details/85783558
今日推荐