五月综合缴情婷婷六月,色94色欧美sute亚洲线路二,日韩制服国产精品一区,色噜噜一区二区三区,香港三级午夜理伦三级三

您現(xiàn)在的位置: 365建站網(wǎng) > 365文章 > TCP讀取報文不完整的問題分析

TCP讀取報文不完整的問題分析

文章來源:365jz.com     點擊數(shù):712    更新時間:2009-10-24 08:40   參與評論

首先解釋一下這個題目, "報文"指的是業(yè)務(wù)層自定義的報文, TCP是流式協(xié)議, 不像UDP那樣是報文協(xié)議.

某兩個系統(tǒng)間進行網(wǎng)絡(luò)交互, 請求報文的格式為:

<json串>&sig=xxx

SYS-ATM作為請求方, 用PHP的stream_socket_sendto()進行發(fā)送. SYS-SIM開發(fā)服務(wù)器端, 使用Python的twisted框架. 上線后, 出現(xiàn)問題, 服務(wù)器端接收到的報文不完整. 例如, json串只讀了一半, 或者缺少"&sig=xxx", 缺少的數(shù)據(jù)是隨機的, 但只缺少尾部, 已經(jīng)接收到數(shù)據(jù)沒有差錯.

發(fā)送方代碼:

$str = sprintf('json=%s&sig=%s', $json, $sig);
stream_socket_sendto($fp, $str);

接收方代碼:

class XServer(Protocol):
def dataReceived(self, data):
#處理一個報文

factory = Factory()
factory.protocol = XServer
reactor.listenTCP(19009, factory)
reactor.run()

我們通過PHP和Python的API文檔, 以及我們對網(wǎng)絡(luò)協(xié)議和套接口的理解來分析.

問題1: 發(fā)送緩沖太小了嗎?(發(fā)送方分包了嗎?)

我們首先想到的原因會不會是, 發(fā)送方的發(fā)送緩沖比一個報文小, 所以"分包"了? 不過仔細一想, 這個問題出發(fā)點本身就是錯誤的. 因為TCP協(xié)議是流式協(xié)議, 不存在"分包"的問題, 因為TCP只能看到字節(jié)流, 不認識報文(包). 所以, 發(fā)送方的發(fā)送緩沖大小不影響接收.

問題2: 接收緩沖太小了嗎?

懷疑完發(fā)送緩沖, 現(xiàn)在來懷疑一下接收緩沖. 因為使用的是TCP協(xié)議, 所以, 就算是只讀到一個字節(jié)的數(shù)據(jù), dataReceived()也可能被調(diào)用一次, 所以, 在dataReceived()中把接收到的數(shù)據(jù)當作一個報文, 就犯了邏輯錯誤, 與接收緩沖的大小無關(guān). 而且, dataReceived()的API文檔提到: Please keep in mind that you will probably need to buffer some data.

問題1和問題2都有相同的錯誤, 那就是錯誤地把TCP當作是基于報文的協(xié)議. 使用TCP, 如果應(yīng)用層協(xié)議不是基于報文的, 你可以在每一次讀數(shù)據(jù)之后對數(shù)據(jù)進行處理, 比如, echo程序. 如果應(yīng)用層協(xié)議是基于報文的, 那么, 你必須自己組裝報文; 或者, 一次TCP會話只發(fā)送一個報文, 通過連接關(guān)閉來顯示聲明報文發(fā)送完畢. 而一個報文可能需要多次讀操作才能組裝完畢, 也可能一次讀包含了多于一個報文(如果不是停止等待應(yīng)答的話).

結(jié)論:

1. 重新定義報文格式, 基于行的協(xié)議

基于TCP socket的程序, 有幾種方式可用來實現(xiàn)報文協(xié)議:

1. 報文中聲明報文數(shù)據(jù)的長度.
2. 使用分隔符.
3. 發(fā)送方發(fā)送完一個報文后關(guān)閉連接.

業(yè)務(wù)層本意上是想使用一種基于報文的協(xié)議, 但所定義的報文格式并沒有提供報文分隔符或者長度字段, 這就要求程序進行語義分析, 增加了實現(xiàn)難度. 現(xiàn)在改成使用換行符作為分隔符.

2. 改寫接收端代碼, 使用基于行的接口

class XServer(LineServer):
def lineReceived(self, data):
#處理一個報文

前面提到, 我們必須自己組裝報文, 但這不代表我們要自己寫組裝代碼, 行IO庫可以替我們做這項工作. LineServer實現(xiàn)了基于行的協(xié)議, 只有讀到完整的一行, lineReceived()才會調(diào)用.

姊妹篇: 編寫基于TCP的應(yīng)用程序 http://www.ideawu.net/blog/?p=429

你現(xiàn)在看的文章是: TCP讀取報文不完整的問題分析  

如對本文有疑問,請?zhí)峤坏浇涣髡搲瑥V大熱心網(wǎng)友會為你解答??! 點擊進入論壇

發(fā)表評論 (712人查看,0條評論)
請自覺遵守互聯(lián)網(wǎng)相關(guān)的政策法規(guī),嚴禁發(fā)布色情、暴力、反動的言論。
昵稱:
最新評論
------分隔線----------------------------

其它欄目

· 建站教程
· 365學習

業(yè)務(wù)咨詢

· 技術(shù)支持
· 服務(wù)時間:9:00-18:00
365建站網(wǎng)二維碼

Powered by 365建站網(wǎng) RSS地圖 HTML地圖

copyright © 2013-2024 版權(quán)所有 鄂ICP備17013400號