Re: [問題] socket 傳檔不完整
※ 引述《dremel (hadoop)》之銘言:
: 小弟初學 練習SOCKET
: 我從良葛葛java教學網站上那
: copy JAVA SOCKET
: http://ideone.com/raPS80 SERVER端
: http://ideone.com/T5rkQt CLIENT端
: 一開始我在同一台電腦不同資料夾做檔案傳輸
: 步驟>先執行SERVER>使SERVER頃聽
: 在執行CLIENT>SERVER會接收檔案。
: 一開始我在同一台電腦不同資料夾做檔案傳輸,這樣是成功的!
: (IP為127.0.0.1)
: 但若我在不同的電腦上作傳輸(更改另一台PC的IP)
: SERVER端放PC1
: CLIENT端放PC2
: 我發現檔案是有傳過來但傳得不完整,檔案的大小總是會少幾個BYTE
: 使這個傳過來的檔案無發開啟!!!
: 是這支程式哪一行有問題嗎?
: 好像只能在單一的電腦傳才能成功。
: 麻煩高手求救 謝謝
你附上的程式碼,理論上你在同一台電腦上測一樣會出錯,只是機率比較低而已。
主要的問題在於 framing 沒有做好。主要出錯的是在 server site 這一方。
至於出錯的部分在於 BufferedInputStream 的使用方式,這個錯誤的使用方式
其實蠻常見到,只是少有人去注意它。
先談一下 BufferedInputStream 的特性,它採 decorator pattern,持有另一個
InputStream,而自己偽裝成 InputStream。它內部還有一個 buffer(如其名),
每當 BufferedInputStream 執行任何 read/skip 操作時,它會盡量去消耗他持有
的 InputStream,來把 buffer 填滿。
因為這個特性,我們必須假設每次對 BufferedInputStream 執行了 read 操作
後,來源 InputStream 已經被消耗了一大段,這一段會是(雖然不總是)比從
BufferedInputStream 取出來的還多。也就是
BufferedInputStream 取出來的 + BufferedInputStream 內部 buffer 剩的
= 來源 InputStream 所消耗的
所以當你把一個 InputStream S decorate 成 BufferedInputStream B 後,有
執行過 read/skip 操作,那麼你就要繼續使用 B 來消耗 S 內的數據,否則你
以其他方式從 S 取得的數據流就可能是不完整的(很大的可能有一些部分在 B 的
buffer 裡)。
*上述所提同樣適用在 BufferedReader 上。
目前 client site 是先傳檔名、換行後接檔案內容,那 server site 要自己去
判斷出屬於檔名的部分(以換行來切割),這必須要雙方去協調定義好"換行"的部分。
這種簡單的應用情景下,比較簡單的方式是透過 DataOutput 的 writeUTF 操作
來傳遞一個字串(String),其做法是把字串以 UTF-8 編碼後的長度先以兩個 bytes
送出,然後是編碼後的 byte sequence;DataInput - readUTF 則是反過來。
我稍微修改後的程式碼供你參考
Client2(http://ideone.com/y6fdEl)
Server2(http://ideone.com/Ay0vD3)
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 218.166.238.27
※ 編輯: sbrhsieh 來自: 218.166.238.27 (12/09 16:22)
推
12/09 19:27, , 1F
12/09 19:27, 1F
推
12/09 20:08, , 2F
12/09 20:08, 2F
→
12/09 20:25, , 3F
12/09 20:25, 3F
推
12/09 20:33, , 4F
12/09 20:33, 4F
→
12/09 21:44, , 5F
12/09 21:44, 5F
推
12/09 22:21, , 6F
12/09 22:21, 6F
推
12/10 10:10, , 7F
12/10 10:10, 7F
推
12/11 16:17, , 8F
12/11 16:17, 8F
推
04/08 23:26, , 9F
04/08 23:26, 9F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 2 篇):
java 近期熱門文章
PTT數位生活區 即時熱門文章