TCP(transport control protocol茸歧,傳輸控制協(xié)議)是面向連接的倦炒,面向流的,提供高可靠性服務(wù)软瞎。收發(fā)兩端(客戶端和服務(wù)器端)都要有一一成對的socket逢唤,因此,發(fā)送端為了將多個(gè)發(fā)往接收端的包涤浇,更有效的發(fā)到對方鳖藕,使用了優(yōu)化方法(Nagle算法),將多次間隔較小且數(shù)據(jù)量小的數(shù)據(jù)只锭,合并成一個(gè)大的數(shù)據(jù)塊著恩,然后進(jìn)行封包。這樣蜻展,接收端页滚,就難于分辨出來了,必須提供科學(xué)的拆包機(jī)制铺呵。即面向流的通信是無消息保護(hù)邊界的裹驰。
UDP(user datagram protocol,用戶數(shù)據(jù)報(bào)協(xié)議)是無連接的片挂,面向消息的幻林,提供高效率服務(wù)。不會(huì)使用塊的合并優(yōu)化算法音念, 由于UDP支持的是一對多的模式沪饺,所以接收端的skbuff(套接字緩沖區(qū))采用了鏈?zhǔn)浇Y(jié)構(gòu)來記錄每一個(gè)到達(dá)的UDP包,在每個(gè)UDP包中就有了消息頭(消息來源地址闷愤,端口等信息)整葡,這樣,對于接收端來說讥脐,就容易進(jìn)行區(qū)分處理了遭居。即面向消息的通信是有消息保護(hù)邊界的啼器。
由于TCP無消息保護(hù)邊界, 需要在消息接收端處理消息邊界問題。
粘包的原因
發(fā)送端需要等緩沖區(qū)滿才發(fā)送出去俱萍,造成粘包
接收方不及時(shí)接收緩沖區(qū)的包端壳,造成多個(gè)包接收
斷包的原因
以太網(wǎng)中存在一個(gè)對于幀的有效數(shù)據(jù)大小的限制,即MTU枪蘑,以太網(wǎng)的MTU為1500字節(jié)损谦。所謂斷包就是說發(fā)送端一次發(fā)送的消息長度過大,如果超過了MTU岳颇,那么ip會(huì)對其進(jìn)行分片照捡,導(dǎo)致接收端接收到消息后,無法確定是否是一個(gè)完整的消息话侧。
粘包/斷包的解決思路
粘包/斷包問題的最本質(zhì)原因在與接收對等方無法分辨消息與消息之間的邊界在哪麻敌。
通過使用某種方案給出邊界,例如:
發(fā)送定長包掂摔。如果每個(gè)消息的大小都是一樣的,那么在接收對等方只要累計(jì)接收數(shù)據(jù)赢赊,直到數(shù)據(jù)等于一個(gè)定長的數(shù)值就將它作為一個(gè)消息乙漓;
包尾加上\r\n標(biāo)記。FTP協(xié)議正是這么做的释移。但問題在于如果數(shù)據(jù)正文中也含有\(zhòng)r\n叭披,則會(huì)誤判為消息的邊界;
包頭加上包體長度玩讳。包頭是定長的4個(gè)字節(jié)涩蜘,說明了包體的長度。接收對等方先接收包體長度熏纯,依據(jù)包體長度來接收包體同诫;
使用更加復(fù)雜的應(yīng)用層協(xié)議。