作者sbrhsieh (十年一梦)
看板java
标题Re: [问题] socket 传档不完整
时间Mon Dec 9 16:13:59 2013
※ 引述《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)
1F:推 gmoz:赞 12/09 19:27
2F:推 dream1124:sb大不知道在哪上班, 令人好想去当你同事 12/09 20:08
3F:→ luoqr:Java API 应该让你来写的 12/09 20:25
4F:推 LaPass:推 12/09 20:33
5F:→ DeathWatch:一点都不错 解释得真棒 之前碰过这问题 12/09 21:44
6F:推 danny8376:推~~~ 12/09 22:21
7F:推 Killercat:大推 这复杂机制可以解释得那麽清楚 XD 12/10 10:10
8F:推 dremel:推~~ 12/11 16:17
9F:推 kaufmann:有看有推 04/08 23:26