鍍金池/ 問答/Java  Linux/ tcp socket 發(fā)送文件,客戶端如何判斷接收到的是完整的文件?

tcp socket 發(fā)送文件,客戶端如何判斷接收到的是完整的文件?

客戶端從socket 讀取文件內(nèi)容,如何知道什么時(shí)候讀到文件的結(jié)尾? 以及接受到讀到的文件是否完整?
測(cè)試代碼發(fā)現(xiàn)有時(shí)候,接收到的文件是原文件的兩倍大小,怎么回事?

回答
編輯回答
孤巷
客戶端從socket 讀取文件內(nèi)容,如何知道什么時(shí)候讀到文件的結(jié)尾? 以及接受到讀到的文件是否完整?

無法知道。或者說,只有“你”才知道。

你能知道的信息,是收到了多少字節(jié),收到的內(nèi)容是什么,至于是否“結(jié)尾”,是否“結(jié)束”,那是你邏輯上的事。

而傳輸協(xié)議如何設(shè)計(jì),可以簡(jiǎn)單去了解一下 HTTP 就明白了。

測(cè)試代碼發(fā)現(xiàn)有時(shí)候,接收到的文件是原文件的兩倍大小,怎么回事?

你代碼有問題。

2017年9月1日 08:49
編輯回答
短嘆
  1. tcp socket判斷數(shù)據(jù)是否完整的做法是制定合適的應(yīng)用層協(xié)議解決(當(dāng)然不排除特殊語言將這個(gè)協(xié)議內(nèi)置在自己的socket api中),我不考慮這種特殊情況。

2.用到什么技術(shù)呢?有限狀態(tài)機(jī)。那么有的同學(xué)可能不是很清楚有限狀態(tài)機(jī)是個(gè)什么東西,不要緊,是個(gè)很簡(jiǎn)單東西。以這個(gè)問題舉例,看完就知道了。

  1. 怎么做?很簡(jiǎn)單,我不是要發(fā)文件給對(duì)方嗎,但是文件可能很大,幾百G,也可能很小200B,對(duì)吧。不管怎么樣,我們都沒有辦法假設(shè)認(rèn)為發(fā)送端一次性往socket里面write能全部寫進(jìn)去,也沒有辦法認(rèn)定接收端一次性能read出來。那我們就在發(fā)送的時(shí)候雙方協(xié)商一個(gè)規(guī)則:我要給你發(fā)文件,最先會(huì)發(fā)4個(gè)字節(jié)(具體多少你自己定),這4個(gè)字節(jié)是的值就表示接下來這個(gè)文件的大小。那問題很好解決啦,發(fā)送端先判斷即將發(fā)送的數(shù)據(jù)的大小,往socket中write一個(gè)4個(gè)字節(jié)的數(shù),解決一直往socket中寫文件,其他不用管,一直寫,寫完為止。那么接收端發(fā)現(xiàn)數(shù)據(jù)來了,先別管,讀出4個(gè)字節(jié),然后看這個(gè)數(shù)字是多大,說明接下來我要持續(xù)的讀多少個(gè)字節(jié),就能組成一個(gè)文件。完美解決。假設(shè)我連續(xù)發(fā)3個(gè)文件,沒關(guān)系,接收端都是先讀4個(gè)字節(jié),假設(shè)讀出來數(shù)據(jù)是10G,那么他接著讀10G的數(shù)據(jù)出來,就是這個(gè)文件,接著在讀4個(gè)字節(jié),假設(shè)是200B,那么接著在讀200B個(gè)字節(jié)數(shù)據(jù)出來,就是第二個(gè)文件的大小,以此類推。
  2. 上述的方式就是一個(gè)簡(jiǎn)單的狀態(tài)機(jī)。
2018年5月13日 08:01
編輯回答
半心人

看你的Socket是什么類型的socket了,如果是文件的Socket,在Java里,會(huì)在文件讀完的時(shí)候返回 -1, 而一般 TCP Socket就需要會(huì)通過上層協(xié)議來保證,TCP Socket一般會(huì)有復(fù)用,所以基本上沒有發(fā)完這一說,當(dāng)然你可以選擇在發(fā)送端發(fā)送完文件內(nèi)容以后主動(dòng)關(guān)閉Socket來表示數(shù)據(jù)傳輸完畢,但是這種情況你就沒有辦法區(qū)分出是網(wǎng)絡(luò)抖動(dòng)還是發(fā)送端真的發(fā)完了。

你也可以自己弄一個(gè)最簡(jiǎn)單的協(xié)議,在發(fā)送真正的文件之前先發(fā)送一些別的信息,比如文件長(zhǎng)度,文件MD5之類的,當(dāng)你讀到頭里指定的字節(jié)數(shù)之后就可以直接認(rèn)為已經(jīng)讀完了,比如

文件長(zhǎng)度 文件MD5 真實(shí)的文件內(nèi)容
4字節(jié)(4GB,根據(jù)你最大的文件大小定,保險(xiǎn)可以8字節(jié)) 16字節(jié) 不固定字節(jié)數(shù)
2017年4月5日 19:50