1、Socket又稱套接字
Socket和ServerSocket類庫位於java.net包中。ServerSocket用於服務器,Socket是創建網絡鏈接時使用的,不論是Socket仍是ServerSock它們的工做都是經過SocketImp類及其子類完成的。
套接字之間的鏈接過程能夠分爲四個步驟:服務器監聽,客戶端請求服務器,服務器確認,客戶端確認,進行通訊。
IO(BIO)和NIO的區別:其本質就是阻塞和非阻塞的區別。
阻塞概念:應用程序在獲取網絡數據的時候,若是網絡傳輸數據很慢,那麼程序就一直等待,直到傳輸完畢爲止。
非阻塞概念:應用程序直接能夠獲取已經準備就緒好的數據,無需等待。
BIO爲同步阻塞形式,NIO爲同步非阻塞形式。NIO並無實現異步。jdk1.7以後,升級NIO包,支持異步非阻塞通訊模型即NIO2,,0
同步與異步:同步和異步通常是面向操做系統與應用程序對IO操做的層面上來區別的。
同步時,應用程序會直接參與IO讀寫操做,而且咱們的應用程序會直接阻塞到某一個方法上,直到數據準備就緒:或者採用輪詢的策略實時檢查數據的就緒狀態,若是就緒則獲取數據。
異步時,則全部的IO讀寫操做交給操做系統處理,與咱們的應用程序沒有直接關係,咱們程序不須要關心IO讀寫,當操做系統完成了IO讀寫操做時,
會給咱們應用程序發送通知,咱們的應用程序直接拿走數據便可。java
2、netty實現通訊的步驟:
1.建立兩個的NIO線程組,一個專門用於網絡事件處理,另外一個則進行網絡通訊讀寫。
2.建立一個ServerBootstrap對象,配置netty的一系列參數,例如接受傳出數據的緩存大小等。
3.建立一個實際處理數據的類Channellenitializer,進行初始化的準備工做,好比設置接受傳出數據的字符集。格式。已經實際處理數據的接口。
4.綁定端口,執行同步阻塞方法等待服務器端啓動便可。
3、服務端:ctx.writeAndFlush(Unplooled.copiedBuffer(response.getBytes())).
addListener(ChannelFutureListener.CLOSE);發一次關閉一次至關於短鏈接,若是不關閉就至關於長鏈接(沒有add)。
4、能夠開啓多個端口
b.bind(8765).sync();
b.bind(8766).sync();
可是處理的能力沒加強,增長了接受能力。
web
5、TCP粘包、拆包的問題
TCP是一個流協議,所謂流就是沒有界限的遺傳數據。在業務上,咱們一個完整的包可能會被TCP分紅多個包進行發送,也可能把多個小包封裝成一個大的數據包發送出去,這就是所謂的TCP粘包、拆包的問題。
分析TCP拆包問題產生的緣由:
1.應用程序write寫入的字節大小大於套接口發送緩存區的大小。緩存
2.進行MSS大小的TCP分段
3.以太網幀的payload大於MTU進行IP分片
解決方案:
1.消息定長,例如每一個報文的大小固定爲200個字節,若是不夠,空位補空格。
2.在包尾增長特殊字符進行分割,例如回車等。
3.將消息分爲消息頭和消息體,在消息頭中包含表示消息總長度的字段,而後進行業務邏輯的處理。
netty如何去解決粘包、拆包的問題:
分隔符類DelimiterBasedFrameDecoder(自定義分隔符)
FixedLengthFrameDecoder(定長)
netty自定義協議服務器
netty udp websocket
netty最佳實踐
一是數據通訊:考慮兩臺機器(甚至多臺)使用netty的怎樣進行通訊,我的認爲如下三種:
1.使用長鏈接通道不斷開的形式進行通訊,也就是服務器和客戶端的通道一直處於開啓狀態,若是服務器性能足夠好,而且咱們的客戶端數量也比較少的狀況下,我仍是比較推薦的,
2.一次性批量提交數據,採用短鏈接方式,也就是咱們會把數據保存在本地臨時緩存區或者臨時表裏,當達到臨界值進行一次性批量提交,又或者根據定時任務輪詢提交,這種
狀況弊端是作不到實時性傳輸,在對實時性不高的應用程序中能夠推薦使用。
3.咱們能夠一種特殊的長鏈接,在指定某一時間以內,服務器與某臺客戶端沒有任何通訊,則斷開鏈接。下次鏈接則是客戶端向服務器發送請求的時候,再次創建鏈接。可是這種模式咱們須要考慮2個因素:
如何在超時後關閉通道?關閉通道後咱們又如何再次創建鏈接?
客戶端宕機時,咱們無需考慮,下次客戶端重啓以後咱們就能夠與服務器創建鏈接,可是服務器宕機時,咱們的客戶端如何與服務器進行鏈接呢?
websocket