您现在的位置是:主页 > news > cookie做网站访问量/seo专业课程

cookie做网站访问量/seo专业课程

admin2025/5/25 4:14:34news

简介cookie做网站访问量,seo专业课程,公司推广网站怎么做,做赚钱问卷调查的网站好文章目录演示代码下一章 基于Netty的WebSocket协议开发演示 实现效果大致如下: 启动 HttpFileServer 访问连接 点击文件也是可以直接下载 代码 HttpFileServer Slf4j public class HttpFileServer {private static final String DEFAULT_URL "/src/ma…

cookie做网站访问量,seo专业课程,公司推广网站怎么做,做赚钱问卷调查的网站好文章目录演示代码下一章 基于Netty的WebSocket协议开发演示 实现效果大致如下: 启动 HttpFileServer 访问连接 点击文件也是可以直接下载 代码 HttpFileServer Slf4j public class HttpFileServer {private static final String DEFAULT_URL "/src/ma…

文章目录

    • 演示
    • 代码
    • 下一章 基于Netty的WebSocket协议开发

演示

实现效果大致如下:
启动 HttpFileServer
在这里插入图片描述
访问连接
在这里插入图片描述
在这里插入图片描述

点击文件也是可以直接下载

代码

HttpFileServer

@Slf4j
public class HttpFileServer {private static final String DEFAULT_URL = "/src/main";public void run(final int port, final String url) throws Exception{EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception{// http解码器会生成多个消息对象ch.pipeline().addLast("http-decoder", new HttpRequestDecoder());// HttpObjectAggregator 解码器 将多个消息转换为单一的 FullHttpRequest 或者 FullHttpResponsech.pipeline().addLast("http-aggregator", new HttpObjectAggregator(65536));// 添加 HTTP 响应编码器对 HTTP 响应进行编码ch.pipeline().addLast("http-encoder", new HttpResponseEncoder());// 添加 ChunkedWriteHandler 支持异步发送大的码流(例如打的文件),但不占用过多的内存,防止发送Java内存溢出ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler());// 添加 HttpFileServerHandler 用于文件服务器业务处理ch.pipeline().addLast("fileServerHandler", new HttpFileServerHandler(url));}});ChannelFuture future = b.bind("127.0.0.1", port).sync();log.info("HTTP 文件目录服务器启动,网址为: http://127.0.0.1:{}{}",port, url);future.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}public static void main(String[] args) throws Exception{int port = 8080;if (args.length > 0) {port = Integer.parseInt(args[0]);}String url = DEFAULT_URL;if (args.length > 1) {url = args[1];}new HttpFileServer().run(port, url);}
}

HttpFileServerHandler

public class HttpFileServerHandler extendsSimpleChannelInboundHandler<FullHttpRequest> {private final String url;public HttpFileServerHandler(String url) {this.url = url;}@Overridepublic void messageReceived(ChannelHandlerContext ctx,FullHttpRequest request) throws Exception {//对HTTP请求消息的解码结果进行判断if (!request.getDecoderResult().isSuccess()) {//如果解码失败直接构造400错误返回sendError(ctx, BAD_REQUEST);return;}//如果不是GET请求就返回405错误if (request.getMethod() != GET) {sendError(ctx, METHOD_NOT_ALLOWED);return;}final String uri = request.getUri();final String path = sanitizeUri(uri);//如果构造的路径不合法就返回403错误if (path == null) {sendError(ctx, FORBIDDEN);return;}//使用URI路径构造file对象,如果是文件不存在或是隐藏文件就返回404File file = new File(path);if (file.isHidden() || !file.exists()) {sendError(ctx, NOT_FOUND);return;}//如果是目录就发送目录的链接给客户端if (file.isDirectory()) {if (uri.endsWith("/")) {sendListing(ctx, file);} else {sendRedirect(ctx, uri + '/');}return;}//判断文件合法性if (!file.isFile()) {sendError(ctx, FORBIDDEN);return;}RandomAccessFile randomAccessFile = null;try {// 以只读的方式打开文件randomAccessFile = new RandomAccessFile(file, "r");} catch (FileNotFoundException fnfe) {sendError(ctx, NOT_FOUND);return;}//获取文件的长度构造成功的HTTP应答消息long fileLength = randomAccessFile.length();//创建成功的 HTTP 响应消息HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);//设置消息头的 content lengthsetContentLength(response, fileLength);//设置消息头的 content typesetContentTypeHeader(response, file);//判断是否是keepAlive,如果是就在响应头中设置CONNECTION为keepAliveif (isKeepAlive(request)) {response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);}//发送响应消息ctx.write(response);ChannelFuture sendFileFuture;//通过Netty的ChunkedFile对象直接将文件写入到发送缓冲区中sendFileFuture = ctx.write(new ChunkedFile(randomAccessFile, 0,fileLength, 8192), ctx.newProgressivePromise());//为sendFileFuture添加监听器,如果发送完成打印发送完成的日志sendFileFuture.addListener(new ChannelProgressiveFutureListener() {@Overridepublic void operationProgressed(ChannelProgressiveFuture future,long progress, long total) {if (total < 0) { // total unknownSystem.err.println("Transfer progress: " + progress);} else {System.err.println("Transfer progress: " + progress + " / "+ total);}}@Overridepublic void operationComplete(ChannelProgressiveFuture future)throws Exception {System.out.println("Transfer complete.");}});//如果使用chunked编码,最后需要发送一个编码结束的空消息体,将LastHttpContent.EMPTY_LAST_CONTENT发送到缓冲区中,//来标示所有的消息体已经发送完成,同时调用flush方法将发送缓冲区中的消息刷新到SocketChannel中发送ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);//如果是非keepAlive的,最后一包消息发送完成后,服务端要主动断开连接if (!isKeepAlive(request)) {lastContentFuture.addListener(ChannelFutureListener.CLOSE);}}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {cause.printStackTrace();if (ctx.channel().isActive()) {sendError(ctx, INTERNAL_SERVER_ERROR);}}private static final Pattern INSECURE_URI = Pattern.compile(".*[<>&\"].*");private String sanitizeUri(String uri) {try {//使用UTF-8对URL进行解码uri = URLDecoder.decode(uri, "UTF-8");} catch (UnsupportedEncodingException e) {try {//解码失败就使用ISO-8859-1进行解码uri = URLDecoder.decode(uri, "ISO-8859-1");} catch (UnsupportedEncodingException e1) {//仍然失败就返回错误throw new Error();}}if (!uri.startsWith(url)) {return null;}//解码成功后对uri进行合法性判断,避免访问无权限的目录if (!uri.startsWith("/")) {return null;}//将硬编码的文件路径分隔符替换为本地操作系统的文件路径分隔符uri = uri.replace('/', File.separatorChar);if (uri.contains(File.separator + '.')|| uri.contains('.' + File.separator) || uri.startsWith(".")|| uri.endsWith(".") || INSECURE_URI.matcher(uri).matches()) {return null;}//使用当前运行程序所在的工程目录+URI构造绝对路径return System.getProperty("user.dir") + File.separator + "06-netty" +  uri;}private static final Pattern ALLOWED_FILE_NAME = Pattern.compile("[A-Za-z0-9][-_A-Za-z0-9\\.]*");//发送目录的链接到客户端浏览器private static void sendListing(ChannelHandlerContext ctx, File dir) {//创建成功的http响应消息FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);//设置消息头的类型是html文件,不要设置为text/plain,客户端会当做文本解析response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");//构造返回的html页面内容StringBuilder buf = new StringBuilder();String dirPath = dir.getPath();buf.append("<!DOCTYPE html>\r\n");buf.append("<html><head><title>");buf.append(dirPath);buf.append(" 目录:");buf.append("</title></head><body>\r\n");buf.append("<h3>");buf.append(dirPath).append(" 目录:");buf.append("</h3>\r\n");buf.append("<ul>");buf.append("<li>链接:<a href=\"../\">..</a></li>\r\n");for (File f : dir.listFiles()) {if (f.isHidden() || !f.canRead()) {continue;}String name = f.getName();if (!ALLOWED_FILE_NAME.matcher(name).matches()) {continue;}buf.append("<li>链接:<a href=\"");buf.append(name);buf.append("\">");buf.append(name);buf.append("</a></li>\r\n");}buf.append("</ul></body></html>\r\n");//分配消息缓冲对象ByteBuf buffer = Unpooled.copiedBuffer(buf, CharsetUtil.UTF_8);//将缓冲区的内容写入响应对象,并释放缓冲区response.content().writeBytes(buffer);buffer.release();//将响应消息发送到缓冲区并刷新到SocketChannel中ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);}private static void sendRedirect(ChannelHandlerContext ctx, String newUri) {FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, FOUND);response.headers().set(LOCATION, newUri);ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);}private static void sendError(ChannelHandlerContext ctx,HttpResponseStatus status) {FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1,status, Unpooled.copiedBuffer("Failure: " + status.toString()+ "\r\n", CharsetUtil.UTF_8));response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);}private static void setContentTypeHeader(HttpResponse response, File file) {MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();response.headers().set(CONTENT_TYPE,mimeTypesMap.getContentType(file.getPath()));}
}

下一章 基于Netty的WebSocket协议开发