mina處理斷包和粘包
mina中有個內建類CumulativeProtocolDecoder是專門用來處理斷包和粘包的。該類的api文件中有個實現的例子。
類org.apache.mina.filter.codec.CumulativeProtocolDecoder
public abstract class CumulativeProtocolDecoder extends ProtocolDecoderAdapter {
private final AttributeKey BUFFER = new AttributeKey(getClass(), "buffer");
public void decode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception {
if (!session.getTransportMetadata().hasFragmentation()) { //用來判斷是否還有分幀(斷包)
while (in.hasRemaining()) {
if (!doDecode(session, in, out)) {
break;
}
}
return;
}
////處理斷包,省略
............................................
}
//需要實現的方法
protected abstract boolean doDecode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception;
}
CumulativeProtocolDecoder是一個抽象類,必須繼承並實現其doDecode方法,使用者自定義協議的拆分就應該寫在doDecode方法中,下面的類MessageDecoder是一個實現的例子。MessageDecoder解碼網路資料到一種有兩位元組長度頭的自定義訊息協議格式。
/**
* 斷包和粘包處理,處理後的訊息為一個或多個完整的資料訊息
* @author blc
*/
public class MessageDecoder extends CumulativeProtocolDecoder {
/*
* (non-Javadoc)
*
* @see
* org.apache.mina.filter.codec.CumulativeProtocolDecoder#doDecode(org.apache
* .mina.core.session.IoSession, org.apache.mina.core.buffer.IoBuffer,
* org.apache.mina.filter.codec.ProtocolDecoderOutput)
*/
@Override
protected boolean doDecode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception {
in.order(ServerConfig.ByteEndian); //位元組序, ServerConfig.ByteEndian = ByteOrder.LITTLE_ENDIAN
//訊息buf
IoBuffer buf = IoBuffer.allocate(ServerConfig.MessageMaxByte); //ServerConfig.MessageMaxByte 最大訊息位元組數
buf.order(ServerConfig.ByteEndian);
//考慮以下幾種情況:
// 1. 一個ip包中只包含一個完整訊息
// 2. 一個ip包中包含一個完整訊息和另一個訊息的一部分
// 3. 一個ip包中包含一個訊息的一部分
// 4. 一個ip包中包含兩個完整的資料訊息或更多(迴圈處理在父類的decode中)
if (in.remaining() > 1) {
int length = in.getShort(in.position());
if (length < 4) {
throw new ServerException("Error net message. (Message Length="+length+")");
}
if (length > ServerConfig.MessageMaxByte) {
throw new ServerException("Error net message. Message Length("+length+") > MessageMaxByte("+ServerConfig.MessageMaxByte+")");
}
if (length > in.remaining()) return false;
//複製一個完整訊息
byte[] bytes = new byte[length];
in.get(bytes);
buf.put(bytes);
buf.flip();
out.write(buf);
return true;
} else {
return false;
}
}
}
二. 使用
將上面的解碼器作為一個過濾器配置到mina中即可,在spring中的配置方法如下:
<!-- 協議過濾器,包括解碼和譯碼 -->
<bean id="protocolCodecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter">
<constructor-arg>
<bean id="factory" class="server.ClientConnServer.MessageCodecFactory"></bean>
</constructor-arg>
</bean>
<!-- 將協議過濾器配置到mina的過濾鏈中 -->
<bean id="filterChainBuilder" class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
<property name="filters">
<map>
<entry key="protocolCodecFilter" value-ref="protocolCodecFilter" />
</map>
</property>
</bean>
<!-- 處理器 -->
<bean id="clientConnHandler" class="server.ClientConnServer.ClientConnHandler" />
<!-- socket接收器,接收客戶端連線 -->
<bean id="ioAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor" destroy-method="unbind">
<!-- <property name="defaultLocalAddress" value=":161" />-->
<property name="handler" ref="clientConnHandler" />
<property name="reuseAddress" value="true" />
<property name="filterChainBuilder" ref="filterChainBuilder" />
</bean>
要配置協議過濾器,必須使用一個ProtocolCodecFactory ,下面是簡單實現
public class MessageCodecFactory implements ProtocolCodecFactory {
private final MessageEncoder encoder;
private final MessageDecoder decoder;
public MessageCodecFactory() {
encoder = new MessageEncoder();
decoder = new MessageDecoder();
}
/* (non-Javadoc)
* @see org.apache.mina.filter.codec.ProtocolCodecFactory#getDecoder(org.apache.mina.core.session.IoSession)
*/
@Override
public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return decoder;
}
/* (non-Javadoc)
* @see org.apache.mina.filter.codec.ProtocolCodecFactory#getEncoder(org.apache.mina.core.session.IoSession)
*/
@Override
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
return encoder;
}
}
/**
* 譯碼器,不做任何事情
*/
public class MessageEncoder extends ProtocolEncoderAdapter {
/* (non-Javadoc)
* @see org.apache.mina.filter.codec.ProtocolEncoder#encode(org.apache.mina.core.session.IoSession, java.lang.Object, org.apache.mina.filter.codec.ProtocolEncoderOutput)
*/
@Override
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
//Do nothing
}
}
相關推薦
mina處理斷包和粘包
一. 解碼方法 mina中有個內建類CumulativeProtocolDecoder是專門用來處理斷包和粘包的。該類的api文件中有個實現的例子。 類org.apache.mina.filter.codec.CumulativeProtocolDecoder public abstract clas
TCP協議-滑動視窗、拆包和粘包
TCP、UDP都可以完成從一端往另一端傳送資料,只是UDP只是負責從傳送端將資料傳送出去就完了,不再管資料是否傳送到接收端是否已經接收到了;而TCP不僅負責傳送資料,還確保資料是否送達,TCP是可靠的,而且它也是可以流控的,管理髮送的速度,不能超過裝置的承受能力。TCP特性1
使用Netty的ReplayingDecoder解決拆包和粘包問題
概述 在 三篇文章中,筆者介紹了在Netty如何解決拆包和粘包問題,其中自定義解碼器處理半包訊息 裡面介紹的方法是在線上實際用過的,經過了超級大流量的驗證,挺靠譜的。下面再介紹另外一種解決半包問題的方法,雖然我沒實際在線上用過,但是可以當成是一種知識
socket編程 粘包和半包 問題的及處理
當前 多少 分包 轉義 保存 長連接 完整 過去 高效 一般在socket處理大數據量傳輸的時候會產生粘包和半包問題,有的時候tcp為了提高效率會緩沖N個包後再一起發出去,這個與緩存和網絡有關系。 粘包 為x.5個包 半包 為0.5個包 由於網絡原因 一次可能會來 0.5/
Socket/TCP粘包、多包和少包, 斷包
關於Tcp封包 很多朋友已經對此作了不少研究,也花費不少心血編寫了實現程式碼和blog文件。當然也充斥著一些各式的評論,自己看了一下,總結一些心得。 首先我們學習一下這些朋友的心得,他們是: //……………… 當然還有太多,很多東西粘來粘區也不知道到底是誰的原作,J 看這些朋友的blog是我建議親自看一
tcp粘包和拆包、斷包
while (1) { var packLen = _.unpack('packLen', tcpBuffer.slice(0, 2)); len = packLen.len; // console.log('pack len------:' + len);
tcp粘包和拆包的處理方案
隨著智慧硬體越來越流行,很多後端開發人員都有可能接觸到socket程式設計。而很多情況下,伺服器與端上需要保證資料的有序,穩定到達,自然而然就會選擇基於tcp/ip協議的socekt開發。開發過程中,經常會遇到tcp粘包,拆包的問題,本文將從產生原因,和解決方案以及work
關於TCP粘包和半包的處理
今日,在程式設計過程中需要在區域網內不同的電腦間傳輸檔案,遇到了TCP協議的粘包和半包現象。經過思考和借鑑,找到了一個比較好的解決方法。因為在傳輸檔案時要先傳輸檔名和檔案大小,然後再傳輸檔案,所以電腦間的應用程式實現了一個小的協議。這個協議需要解碼TCP傳輸的內容。在有粘包
CocoaAsyncSocket + Protobuf 處理粘包和拆包問題
在上一篇文章《iOS之ProtocolBuffer搭建和示例demo》分享環境的搭建, 我們和伺服器進行IM通訊用了github有名的框架CocoaAsynSocket, 然後和伺服器之間的資料媒介是ProtoBuf。然後後面在開發的過程中也碰到了拆包和粘包問題,這方面
Netty中處理TCP粘包和拆包
什麼是粘包和拆包 TCP是個”流”協議,流其實就是沒有界限的一串資料。 TCP底層中並不瞭解上層業務資料的具體含義,它會根據TCP緩衝區的實際情況進行包劃分,所以在TCP中就有可能一個完整地包會被TCP拆分成多個包,也有可能吧多個小的包封裝成一個大的資料包傳
處理粘包和半包有關問題的socket分包Java實現
- 處理粘包和半包問題的socket分包Java實現 只知道原理,程式碼實現還不知道怎麼實現?請高手指點,謝謝!高分饋贈!------解決方案-------------------- 一般在socket處理大資料量傳輸的時候會產生粘包和半包問題,有的時候tcp為了提高效
netty的解碼器和粘包拆包
exception med 增加 這就是 就會 邊界 ali 空格 封裝 Tcp是一個流的協議,一個完整的包可能會被Tcp拆成多個包進行發送,也可能把一個小的包封裝成一個大的數據包發送,這就是所謂的粘包和拆包問題 粘包、拆包出現的原因: 在流傳輸中出現,UDP不會出現粘包,
SOCKET程式設計流位元組和粘包問題readn和writen函式封裝
#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #
Socket:半包及粘包的一種處理方法
先說下思路: 當出現半包情況時,原本一整段的訊息被分成兩部分或多部分,導致用來判斷訊息是否完整的函式無法判斷,所以這時候就將先到達的內容儲存起來,用於與後到達的內容連線在一起。 當出現粘包情況時,訊息A和訊息B緊密的連線在一起,這就導致處理訊息的函式如果不將訊
粘包和半包問題總結
什麼是TCP粘包半包? 假設客戶端分別傳送了兩個資料包D1和D2給服務端,由於服務端一次讀取到的位元組數是不確定的,故可能存在以下4種情況。 (1)服務端分兩次讀取到了兩個獨立的資料包,分別是D1和D2,沒有粘包和拆包; (2)服務端一次接收到了兩個資料包,D1和D2粘合在一起,被稱為
低級別網路介面-socket的應用和粘包現象
套接字的型別 基於檔案型別的套接字家族: AF_UNIX 基於檔案的套接字
Netty學習10-粘包和拆包
1 粘包拆包基本概念 TPC是一個面向流的協議。所謂流就是沒有邊界的一串資料,如同河水般連成一片,其中並沒有分界線。TCP底層並不瞭解上層業務資料的具體含義,它會根據TCP緩衝區的具體情況進行包的劃分,所以在業務上認為,一個完整的包可能會被TCP拆成多個包傳送,也有可能
Tcp粘包和拆包的原因
最近研究Netty網路程式設計,以前專案中也遇到過資料接收過程中資料質量太差問題,很可能是TCP傳輸過程中問題,特此記錄。 問題產生 一個完整的業務可能會被TCP拆分成多個包進行傳送,也有可能把多個小的包封裝成一個大的資料包傳送,這個就是TCP的拆包和封包問
Unity Socket傳輸 TCP粘包和拆包原因以及解決策略
3. 乙太網的payload大於MTU進行IP分片。MTU指:一種通訊協議的某一層上面所能通過的最大資料包大小。如果IP層有一個數據包要傳,而且資料的長度比鏈路層的MTU大,那麼IP層就會進行分片,把資料包分成若干片,讓每一片都不超過MTU。注意,IP分片可以發生在原始傳送端主機上,也可以發生在中間路由器上
java socket編程解決粘包和丟包問題
cat exceptio nal end ddr exc gen main socket ##socket 丟包粘包解決方式 采用固定頭部長度(一般為4個字節),包頭保存的是包體的長度 header+body 包頭+包體 思路是:先讀出一個包頭,得到包體的長度