netty之Http伺服器
1. netty可以做的事情
- netty可以作為RPC的通訊框架
- netty作為長連線伺服器(websockt)
- netty也可以作為http伺服器(不是基於servlet規範)
2. netty的Hello World(Http伺服器)
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class TestServer {
public static void main(String[] args) {
// bossGroup 不斷的從客戶端接受連結,但不會做任何處理,直接轉給 workerGroup
EventLoopGroup bossGroup = new NioEventLoopGroup();
// workerGroup 從 bossGroup 接收到連結,然後獲取引數等進行處理
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new TestServerInitializer());
try {
ChannelFuture channelFuture = serverBootstrap.bind(8899 ).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
public class TestServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("httpServerCodec",new HttpServerCodec());
pipeline.addLast("testHttpServerHandler",new TestHttpServerHandler());
}
}
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;
public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
/**
* 讀取客戶端發起的請求,並向客戶端返回響應的方法
* @param ctx
* @param msg
* @throws Exception
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) {
if (msg instanceof HttpRequest) {
ByteBuf content = Unpooled.copiedBuffer("Hello Word", CharsetUtil.UTF_8);
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
ctx.writeAndFlush(response);
}
}
}
3. netty使用的基本流程
- 啟動一個Bootstrap伺服器,Bootstrap裡面會關聯兩個事件迴圈組(bossGroup、workerGroup)
- bossGroup 用於獲取連結
- workerGroup 用於處理連結
- 伺服器啟動時關聯一個處理器(ChannelHandler)
- 在ChannelHandler中新增若干個自定義或者netty提供的處理器
- 在自定義的處理器(ChannelHandler)中返回響應
- 整個請求處理完畢
netty處理請求進入的類一般是xxxInbound(ChannelInboundHandler)
netty處理響應輸出的類一般是xxxOutbound(ChannelOutboundHandler)
4. TestHttpServerHandler分析
我們複寫一下父類中的一些方法,這些方法在事件發生時會被回撥
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;
public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
/**
* 讀取客戶端發起的請求,並向客戶端返回響應的方法
* @param ctx
* @param msg
* @throws Exception
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) {
if (msg instanceof HttpRequest) {
ByteBuf content = Unpooled.copiedBuffer("Hello Word", CharsetUtil.UTF_8);
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
ctx.writeAndFlush(response);
}
}
// 3. 管道活躍
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelActive");
super.channelActive(ctx);
}
// 2. 管道註冊
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelRegistered");
super.channelRegistered(ctx);
}
// 1. 新的管道新增
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerAdded");
super.handlerAdded(ctx);
}
// 4. 管道不活躍
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelInactive");
super.channelInactive(ctx);
}
// 5. 管道取消註冊
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelUnregistered");
super.channelUnregistered(ctx);
}
}
我們使用curl訪問,發現控制檯列印資訊如下:
curl "http://localhost:8899"
handlerAdded
channelRegistered
channelActive
channelInactive
channelUnregistered
- handlerAdded在父級介面(ChannelHandler)中的doc如下:
/**
* Gets called after the {@link ChannelHandler} was added to the actual context and it's ready to handle events.
*/
void handlerAdded(ChannelHandlerContext ctx) throws Exception;
意思是handlerAdded將在ChannelHandler被新增到真實的上下文後被呼叫,這時表示上下文已經準備好處理事件了。
- channelRegistered在父級介面(ChannelInboundHandler)中的doc如下:
The {@link Channel} of the {@link ChannelHandlerContext} was registered with its {@link EventLoop}
意思是ChannelHandlerContext(上下文)的Channel(管道)註冊了它的EventLoop(事件迴圈)
- channelActive在父級介面(ChannelInboundHandler)中的doc如下:
The {@link Channel} of the {@link ChannelHandlerContext} is now active
意思是ChannelHandlerContext(上下文)的Channel(通道)現在處於活躍狀態
- channelInactive在父級介面(ChannelInboundHandler)中的doc如下:
The {@link Channel} of the {@link ChannelHandlerContext} was registered is now inactive and reached its end of lifetime.
意思是ChannelHandlerContext(上下文)註冊的Channel(通道)當前處於不活躍狀態,並且到達了它生命週期的末尾
- channelUnregistered在父級介面(ChannelInboundHandler)中的doc如下:
The {@link Channel} of the {@link ChannelHandlerContext} was unregistered from its {@link EventLoop}
意思是ChannelHandlerContext(上下文)的Channel(通道)從它的EventLoop(事件迴圈)中取消了註冊
我們使用curl請求這五個方法都會被呼叫,但是當我們使用瀏覽器去請求時channelInactive和channelUnregistered可能不會被呼叫,但當我們關閉瀏覽器時這兩個方法就會被呼叫。這是應該目前的瀏覽器時基於HTTP1.1協議,請求完畢時並不會馬上關閉連線,當瀏覽器關閉時連線斷開,服務端就會呼叫以上兩個方法來完成通道的關閉。
相關推薦
netty之Http伺服器
1. netty可以做的事情 netty可以作為RPC的通訊框架 netty作為長連線伺服器(websockt) netty也可以作為http伺服器(不是基於servlet規範) 2. netty的Hello World(Http伺服器) im
06-netty之http之檔案伺服器
Netty是一個NIO框架,讓你快速、簡單的的開發網路應用。它是一種新的開發網路應用的方式,使得開發網路應用更加簡單,容易擴充套件。它隱藏了許多複雜的細節,並提供簡單的api讓你的業務邏輯和網路處理程式碼分離開來。Netty的所有api都是非同步的,如果大家不瞭
基於netty實現http伺服器
匯入netty4的依賴 <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>
使用Netty實現HTTP伺服器
使用Netty實現HTTP伺服器,使用Netty實現httpserver。 Netty是一個非同步事件驅動的網路應用程式框架用於快速開發可維護的高效能協議伺服器和客戶端。Netty經過精心設計,具有豐富的協議,如FTP,SMTP,HTTP以及各種二進位制和基於文字的傳統協議。 Java程式設計師在開發we
Tornado原始碼分析之http伺服器篇
一. Tornado是什麼? Facebook釋出了開源網路伺服器框架Tornado,該平臺基於Facebook剛剛收購的社交聚合網站FriendFeed的實時資訊服務開發而來.Tornado由Python編寫,是一款輕量級的Web伺服器,同時又是一個開發框架。採用非阻
從零編寫c++之http伺服器(3)-http服務
http全稱超文字傳輸協議,可除錯性高,擴充套件性也強。上兩個篇章我們已經擁有了epoll事件驅動框架和執行緒池處理網路事件,接下來我們要先寫一個基礎網路套接字,然後在此基礎上擴展出http的套接字。獻上類圖如下
springboot 2.0中webflux使用netty作為http伺服器的坑
過程略過,直接開始總結:webflux不要使用netty作為http伺服器,ab壓測多次的結果效能比tomcat差上一截。debug模式跟蹤原始碼發現業務程式碼執行在netty的nio執行緒裡,猜測這是導致效能低下的原因。並且nio的執行緒數預設是根據cpu核心數量來設定
lwip之http伺服器
準備工作: 1、下載一個網頁檔案。 2、下載winhex,用winhex開啟網頁檔案,將網頁檔案轉換成c陣列。 具體操作如下: Edit--->Copy All------>C Source 這樣操作後,轉換成的c陣列就被複制到剪下板了。 開啟一個記事本就可以將陣列貼上進去。 lwip相關操作:
Netty實現高效能的HTTP伺服器
16:58:59.130 [nioEventLoopGroup-3-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxSharedCapacityFactor: 2 16:58:59.130 [nioEventLoopGroup-3-1
《netty權威指南》之模擬伺服器之間的心跳檢測
在叢集環境下伺服器之間是要定時進行心跳檢測的,那麼netty可以用來做這件事, 在叢集環境中,選定一臺服務區做master,其餘的做salve 即master <==> server端 salve <==> 客戶端 客戶端定時像服務端傳送
寒假無聊 開啟小專案 http伺服器之二傳送http請求(http客戶機)
目錄 說明 實驗環境 建立tcp 連線 程式碼 說明 通過上一篇部落格, 我們基本瞭解了http伺服器的工作流程,首先客戶機和伺服器建立TCP連線 ,連線建立以後,客戶機發出http請求,伺服器做出響應。所以
使用C#開發HTTP伺服器之支援HTTPS
各位朋友大家好,我是秦元培,歡迎大家關注我的部落格,我的部落格地址是http://qinyuanpei.com。本文是“使用C#開發HTTP伺服器”系列的第六篇文章,在這個系列文章中我們實現了一個基礎的Web伺服器,它支援從本地讀取靜態HTML頁面,支援GE
Netty實現簡單的Http伺服器
之前在upload伺服器的時候,由於tomcat效能瓶頸的的問題,qps無法達到要求,瞭解到Netty.io的高效能,覺得自己寫一個Http接受資料的伺服器來處理客戶段上報的資料,比較簡單,直接貼程式碼了: package com.bonree.browser
Boost.Asio學習之簡單的HTTP伺服器的完善
以上鍊接裡面的原始碼至少有下面兩個問題: 1.只解析了http協議的頭部資訊(header)。 2.沒有對tcp資料包進行合併的處理,如果客戶端的tcp資料是分包發過來的,該程式碼的解析會出錯,所以這是不可預料的錯誤。 以下是修改後的部分程式碼: 1
Unity3d搭建HTTP弱聯網的伺服器搭建及客戶端編寫(一)之java伺服器
HTTP弱聯網java伺服器 通過tomcat搭建java伺服器(linux 1、java環境搭建 java環境較容易搭建,在網上很容易找到相關的教程。 2、tomcat環境搭建 開始配置tomcat: 複製解壓後的檔案到 /opt
使用C#開發HTTP伺服器系列之構建RESTful API
各位朋友大家好,我是秦元培,歡迎大家關注我的部落格,我的部落格地址是http://qinyuanpei.com。到目前為止,“使用C#開發HTTP伺服器”這個系列系列文章目前已經接近尾聲了,雖然我們在伺服器功能的完整性(如支援併發、快取、非同步、Htts等)
Netty5使用者手冊之二:使用netty實現Discard伺服器程式
<span style="font-family:Microsoft YaHei;font-size:14px;">package com.zzj.nio.netty; import io.netty.bootstrap.ServerBootstrap; import io.netty.chan
Netty程式設計——簡單的http伺服器
經常看到Tornado的監聽埠,身為Javaista,tomcat對底層封裝極其喪心病狂,計劃開始手擼一個基於Netty的http伺服器,並不斷完善,順便學習NIO和RPC第一個超級簡單,hello world,本次編碼使用kotlin實現,具體和Java沒有太大區別,接下來
使用C#開發HTTP伺服器系列之Hello World
各位朋友大家好,我是秦元培,歡迎大家關注我的部落格。從今天起,我將開始撰寫一組關於HTTP伺服器開發的系列文章。我為什麼會有這樣的想法呢?因為人們對Web技術存在誤解,認為網站開發是Web技術的全部。其實在今天這樣一個時代,Web技術可謂是無處不在,無論是傳
Android與伺服器端通訊方式(一)之HTTP、TCP、Socket
Android作為客戶端,與伺服器的通訊方式主要有兩種:一種是HTTP通訊,一種是Socket通訊。 一、HTTP、Socket簡介 HTTP通訊:即使用HTTP協議進行通訊,工作原理是客戶端向伺服器端傳送一條HTTP請求,伺服器收到之後先解析客戶