TCP Socket 粘包



這兩天看csdn有一些關于socket粘包,socket緩沖區設置的問題。發現自己不是非常清楚,所以查資料了解記錄一下:

?

一兩個簡單概念長連接與短連接:
1.長連接

??? Client方與Server方先建立通訊連接。連接建立后不斷開。 然后再進行報文發送和接收。

2.短連接

??? Client方與Server每進行一次報文收發交易時才進行通訊連接,交易完成后馬上斷開連接。此種方式經常使用于一點對多點
通訊。比方多個Client連接一個Server.

?

二 什么時候須要考慮粘包問題?

1:假設利用tcp每次發送數據,就與對方建立連接,然后兩方發送完一段數據后,就關閉連接,這樣就不會出現粘包問題(由于僅僅有一種包結構,類似于http協議)。

關閉連接主要要兩方都發送close連接(參考tcp關閉協議)。如:A須要發送一段字符串給B。那么A與B建立連接,然后發送兩方都默認好的協議字符如"hello give me sth abour yourself",然后B收到報文后,就將緩沖區數據接收,然后關閉連接,這樣粘包問題不用考慮到,由于大家都知道是發送一段字符。
2:假設發送數據無結構,如文件傳輸,這樣發送方僅僅管發送,接收方僅僅管接收存儲就ok。也不用考慮粘包
3:假設兩方建立連接,須要在連接后一段時間內發送不同結構數據,如連接后,有好幾種結構:
?1)"hello give me sth abour yourself"
?2)"Don't give me sth abour yourself"
?? 那這種話,假設發送方連續發送這個兩個包出去,接收方一次接收可能會是"hello give me sth abour yourselfDon't give me sth abour yourself" 這樣接收方就傻了,究竟是要干嘛?不知道,由于協議沒有規定這么詭異的字符串,所以要處理把它分包,怎么分也須要兩方組織一個比較好的包結構,所以一般可能會在頭加一個數據長度之類的包,以確保接收。
?

三 粘包出現原因:在流傳輸中出現。UDP不會出現粘包。由于它有消息邊界(參考Windows 網絡編程)
1 發送端須要等緩沖區滿才發送出去,造成粘包
2 接收方不及時接收緩沖區的包。造成多個包接收

解決的方法:
為了避免粘包現象,可採取下面幾種措施。

一是對于發送方引起的粘包現象。用戶可通過編程設置來避免,TCP提供了強制數據馬上傳送的操作指令push,TCP軟件收到該操作指令后。就馬上將本段數據發送出去,而不必等待發送緩沖區滿;二是對于接收方引起的粘包,則可通過優化程序設計、精簡接收進程工作量、提高接收進程優先級等措施,使其及時接收數據,從而盡量避免出現粘包現象。三是由接收方控制,將一包數據按結構字段,人為控制分多次接收,然后合并,通過這樣的手段來避免粘包。

以上提到的三種措施。都有其不足之處。第一種編程設置方法盡管能夠避免發送方引起的粘包,但它關閉了優化算法,降低了網絡發送效率,影響應用程序的性能,一般不建議使用。另外一種方法僅僅能降低出現粘包的可能性,但并不能全然避免粘包,當發送頻率較高時,或因為網絡突發可能使某個時間段數據包到達接收方較快,接收方還是有可能來不及接收。從而導致粘包。

第三種方法盡管避免了粘包,但應用程序的效率較低,對實時應用的場合不適合。


相關文章截取:

一個包沒有固定長度,以太網限制在46-1500字節,1500就是以太網的MTU,超過這個量,TCP會為IP數據報設置偏移量進行分片傳輸,如今一般可同意應用層設置8k(NTFS系)的緩沖區,8k的數據由底層分片,而應用看來僅僅是一次發送。windows的緩沖區經驗值是4k,Socket本身分為兩種。流(TCP)和數據報(UDP),你的問題針對這兩種不同使用而結論不一

樣。甚至還和你是用堵塞、還是非堵塞Socket來編程有關。

1、通信長度,這個是你自己決定的,沒有系統強迫你要發多大的包,實際應該依據需求和網絡狀況來決定。對于TCP,這個長度能夠大點。但要知道,Socket內部默認的收發緩沖區大小大概是8K,你能夠用SetSockOpt來改變。但對于UDP,就不要太大。一般在1024至10K。注意一點。你不管發多大的包,IP層和鏈路層都會把你的包進行分片發送。一般局域網就是1500左右,廣域網就僅僅有幾十字節。分片后的包將經過不同的路由到達接收方。對于UDP而言。要是當中一個分片丟失,那么接收方的IP層將把整個發送包丟棄,這就形成丟包。顯然,要是一個UDP發包佷大。它被分片后,鏈路層丟失分片的幾率就佷大。你這個UDP包。就佷easy丟失,可是太小又影響效率。最好能夠配置這個值,以依據不同的環境來調整到最佳狀態。

send()函數返回了實際發送的長度,在網絡不斷的情況下,它絕不會返回(發送失敗的)錯誤,最多就是返回0。

對于TCP你能夠字節寫一個循環發送。

當send函數返回SOCKET_ERROR時,才標志著有錯誤。但對于UDP,你不要寫循環發送。否則將給你的接收帶來極大的麻煩。所以UDP須要用SetSockOpt來改變Socket內部Buffer的大小,以能容納你的發包。

明白一點,TCP作為流,發包是不會整包到達的,而是源源不斷的到。那接收方就必須組包。而UDP作為消息或數據報,它一定是整包到達接收方。

2、關于接收,一般的發包都有包邊界,首要的就是你這個包的長度要讓接收方知道,于是就有個包頭信息,對于TCP,接收方先收這個包頭信息。然后再收包數據。

一次收齊整個包也能夠,可要對結果是否收齊進行驗證。這也就完畢了組包過程。UDP,那你僅僅能整包接收了。要是你提供的接收Buffer過小。TCP將返回實際接收的長度,余下的還能夠收,而UDP不同的是。余下的數據被丟棄并返回WSAEMSGSIZE錯誤。注意TCP。要是你提供的Buffer佷大,那么可能收到的就是多個發包。你必須分離它們。還有就是當Buffer太小,而一次收不完Socket內部的數據,那么Socket接收事件(OnReceive),可能不會再觸發,使用事件方式進行接收時,密切注意這點。

這些特性就是體現了流和數據包的差別。


相關參考文章:
http://www.cnblogs.com/alon/archive/2009/04/16/1437600.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/541578.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/541578.shtml
英文地址,請注明出處:http://en.pswp.cn/news/541578.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

離散數學和組合數學什么關系_關系類型| 離散數學

離散數學和組合數學什么關系關系類型 (Types of Relation) There are many types of relation which is exist between the sets, 集合之間存在許多類型的關系, 1. Universal Relation 1.普遍關系 A relation r from set a to B is said to be universal if: R A…

springboot公共模塊打包_解決SpringBoot多模塊發布時99%的問題?

每天都會分享Java架構文章,喜歡的朋友關注我。ps:文末有彩蛋,驚喜等著你如果使用的是 SpringBoot 多模塊的項目,在發布的時候可能遇到各種各樣的問題。本文歸納了以下 8 個原則和發布時經常出現的 4 個問題的解決方案,…

tomcat7的數據庫連接池tomcatjdbc的25個優勢

tomcat的JDBC連接池org.apache.tomcat.jdbc.pool更換或替代嗎Apache Commons DBCP連接池。為什么我們須要一個新的連接池?這里有幾個原因: 1.DBCP 1.x是單線程的。為了成為線程安全的 共享鎖整個池在短時間內在兩個對象 分配和對象返回。注意,這并不適用 下議院DBCP 2.x。 2.D…

weakhashmap_Java WeakHashMap entrySet()方法與示例

weakhashmapWeakHashMap類entrySet()方法 (WeakHashMap Class entrySet() method) entrySet() method is available in java.util package. entrySet()方法在java.util包中可用。 entrySet() method is used to retrieve the mappings that exist in this map to be viewed in …

定義整型數組_C++數組的定義與初始化(學習筆記:第6章 01)

數組的定義與使用[1]數組是具有一定順序關系的若干相同類型變量的集合體,組成數組的變量稱為該數組的元素。數組的定義方括號里面列出的常量表達式是數組每一維的下標個數。數組的下標不管從哪一維它都是從0開始數的。例如:int a[10]; 表示a為整型數組&a…

我們正在經歷一個應用疲憊時代?

在移動互聯網時代到來之后,應用程序成為了智能手機必備,也正因為萬千開發者的參與,才讓移動終端充分發揮出了強大的能量,當然,這些開發者也不斷創造著造富神話,一個小團隊在幾個月的努力之后可能就會成為億…

Java LinkedHashMap values()方法與示例

LinkedHashMap類的values()方法 (LinkedHashMap Class values() method) values() method is available in java.util package. values()方法在java.util包中可用。 values() method is used to get all the values exist in this LinkedHashMap to be viewed in a Collection.…

語句拼接_第2課:一個周末學會R語言數據處理:表拆分和拼接

從一線收集了兩百個文件,要整合到一起?總部一張全國兩百個城市的匯總表,拆成兩百個小文件?開什么玩笑,難道要復制粘貼到天荒地老。。。不用這么麻煩,一個循環,一個語句,實現快速表拆…

Anaconda配置多spyder多python環境

作者:桂。 時間:2017-04-17 22:02:37 鏈接:http://www.cnblogs.com/xingshansi/p/6725298.html 前言 最近在看《統計學習方法》,打算配合《機器學習實戰》一起,可后者的代碼是基于python2.6的: All the co…

pytorch自定義新層demo_從頭學pytorch(十一):自定義層

自定義layer不含模型參數的layer含模型參數的layer核心都一樣,自定義一個繼承自nn.Module的類,在類的forward函數里實現該layer的計算,不同的是,帶參數的layer需要用到nn.Parameter不含模型參數的layer直接繼承nn.Moduleimport torchfrom torch import nnclass CenteredLayer(n…

java日歷類add方法_Java日歷computeTime()方法及示例

java日歷類add方法日歷類computeTime()方法 (Calendar Class computeTime() method) computeTime() method is available in java.util package. java.util包中提供了computeTime()方法 。 computeTime() method is for conversion of current field values to the ms(millisec…

C++——智能指針和RAII

該文章代碼均在gitee中開源 C智能指針hpphttps://gitee.com/Ehundred/cpp-knowledge-points/tree/master/%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88??????? 智能指針 傳統指針的問題 在C自定義類型中,我們為了避免內存泄漏,會采用析構函數的方法釋…

移除元素所有事件監聽_DOM 事件模型或 DOM 事件機制

DOM 事件模型DOM 的事件操作(監聽和觸發),都定義在EventTarget接口。所有節點對象都部署了這個接口,其他一些需要事件通信的瀏覽器內置對象(比如,XMLHttpRequest、AudioNode、AudioContext)也部…

gettimezone_Java日歷getTimeZone()方法與示例

gettimezone日歷類的getTimeZone()方法 (Calendar Class getTimeZone() method) getTimeZone() method is available in java.util package. getTimeZone()方法在java.util包中可用。 getTimeZone() method is used to return this Calendar time zone. getTimeZone()方法用于返…

cass展點不在原位置_cass展點之步驟及方法

cass展點之步驟及方法cass展點是根據手工或坐標正反算軟件自動計算的結果,利用cass軟件將點號、坐標及其高程自動展示到圖紙上的一種方法。其基本步驟和方法如下:一、將井下測點的點號、以及計算好的Y坐標、X坐標、及高程由sheet1復制并粘貼到sheet2上面…

Java BufferedWriter close()方法與示例

BufferedWriter類close()方法 (BufferedWriter Class close() method) close() method is available in java.io package. close()方法在java.io包中可用。 close() method is used to flushes the characters from the stream and later will close it by using close() metho…

ISCC2014-reverse

這是我做reverse的題解。在咱逆向之路上的mark一下,,水平有限,大牛見笑。題目及題解鏈接:http://pan.baidu.com/s/1gd3k2RL 宗女齊姜 果然是僅僅有50分的難度,OD直接找到了flag. 找到殺手 這題用OD做非常麻煩。我改用I…

python 獲取當前時間再往前幾個月_Python 中的時間和日期操作

Python中,對日期和時間的操作,主要使用這3個內置模塊: datetime 、 time 和 calendar 獲取當前時間對應的數字 開發程序時,經常需要獲取兩個代碼位置在執行時的時間差,比如,我們想知道某個函數執行大概耗費了多少時間,就可以使用time.time()來做。 import time before =…

Java BigDecimal restder()方法與示例

BigDecimal類的restder()方法 (BigDecimal Class remainder() method) Syntax: 句法: public BigDecimal remainder(BigDecimal divsr);public BigDecimal remainder(BigDecimal divsr, MathContext ma_co);remainder() method is available in java.math package.…

python程序需要編譯么_python需要編譯么

一個經常聽見的問題,那就是:Python是解釋型的語言嗎?它會被編譯嗎?這個問題沒有想象中那么好回答。和很多人認識世界一樣,習慣以一個簡單的模型去評判一些事物。而事實上,里面包含了很多很多的細節。通常的…