关于InputStream得avaliable()方法的使用

bloodrate 2008-07-15 06:30:23
做一段socket程序,一个客户端一个服务器端,客户端传给服务器端查询条件,服务器端将查询结果以xml形式返回给客户端,很简单得需求吧,现在迷茫于网络流得io操作中

如果流来自于本地文件,那没有问题,现在流来自于网络中得另一台主机,问题来了,起先我这么写

String ling;
while((line = br.readLine())!=null){
.......
}
后来发现卡在最后一次循环得line = br.readLine()处不执行,我猜想网络流不同于本地文件流,不能用!=null来判断文件读取结束,因为在网络流中没有EOF标志位,即便3分钟没有数据传过来,读取端也无法判断到底是网络问题还是确实传完了。

之后我遍想到了avaliable()方法,“下一次可读取得最大字节数”,猜想大概就是网络中一个数据包得大小吧,结果代码修改如下

client:

OutputStream socketOut = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socketOut));
bw.write("hello");
bw.flush();


server:

int i = is.available();
String result;
while(i>0){
byte[] buff = new byte[i];
is.read(buff);
result = result + new String(buff);
i = is.available();
}


结果int i = is.available();有时候能正确返回,有时候则返回0,非常郁闷,谁能讲解一下网络流和avaliable()啊
...全文
220 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
lisino 2008-08-26
  • 打赏
  • 举报
回复
写个循环 设置个超时 在超时时间内 循环 如果没数据进来 线程先sleep一段时间 直到有数据进来 再循环读取
bloodrate 2008-07-16
  • 打赏
  • 举报
回复
楼上说的传输协议是不是这样理解:

在没有协议的时候:
BufferedWriter bw = null;
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(我所要传输的数据);
bw.flush();
socket.shutdownOutput();

增加了协议,比如,代码改为
BufferedWriter bw = null;
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(po(我所要传输的数据));
bw.flush();
socket.shutdownOutput();
方法po封状了数据格式,比如规定在我要传输的数据中每格128个字符插入换行符等等..

不知道理解的对不对,不知道具体协议怎么写,才能让接受端与发送端同步,求教个例子
  • 打赏
  • 举报
回复
如果想通知读取方数据已全部发完,你不用在那儿等了(即使数据接收方的 readxxx 出现上面的流结束标志),可以将发数据方的输出流关闭掉,使用 Socket.shutdownOutput()。
beiouwolf 2008-07-16
  • 打赏
  • 举报
回复
网络读取最好不要用BufferedReader
用InputStream最好
read的时候判断是不是-1
bloodrate 2008-07-16
  • 打赏
  • 举报
回复
按照楼上说的,我好想理解了,在调用int i = is.available();的时候,对面得数据可能还没准备好,可能过100ms才能准备好,所以返回了0,也就是说available()不能用来判断流传送进度
冰思雨 2008-07-16
  • 打赏
  • 举报
回复
发表一个个人意见.
楼主说的最后一个readLine方法无法正常返回,我在编程当中好象没有碰到过这种情况,楼主是不是在发送端没有输入换行符?这样接收端的readLine方法就无法正常返回了.

available方法,我理解是判断缓冲区是否有数据.
那么数据在传输过程中,其实是按byte来传输的.那么,在接收端,同一秒钟有可能接受了很多byte,也有可能什么也没有接收到,这是由于网络环境,硬件设置,以及操作系统的工作方式等多重因素造成的.

TCP的网络传输,一般还要再封装一层协议的,最起码接受端能判断一次接受是否能够结束才可以.
楼主使用的readLine方法,其实,就是以换行符作为一次接收数据的结束符的.
如果在知道发送方发送多么长的数据的时候,我们可以编写程序判断available的返回值>=发送长度的时候,一次性接受.当然,直接用read方法,也是可以的.
其他情况,应该要封装一层传输协议的.
sagezk 2008-07-16
  • 打赏
  • 举报
回复
你整个思路有问题
sagezk 2008-07-16
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 bloodrate 的回复:]
按照楼上说的,我好想理解了,在调用int i = is.available();的时候,对面得数据可能还没准备好,可能过100ms才能准备好,所以返回了0,也就是说available()不能用来判断流传送进度
[/Quote]

对,available() 不能用来判断流传送进度。
bloodrate 2008-07-16
  • 打赏
  • 举报
回复
我把部分代码贴出来吧
client

public String sendRequest(String condition) {
BufferedWriter bw = null;
BufferedReader br = null;
try {
socket = new Socket(host, port);
// 发送关闭命令
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(condition);
bw.flush();
socket.shutdownOutput();
// 接收服务器的反馈
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String result = "";
String line = "";
while((line = br.readLine())!=null){
result = result + line;
}
return result;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}


server

BufferedWriter bw = null;
BufferedReader br = null;
try {
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String result = "";
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = "";
while((line = br.readLine())!=null){
result = result + line;
}
System.out.println("there:"+result);
//转化条件表达式
Map condition = ConditionParser.convert(result.trim());
//获得相应的业务实现
IBussiness ib = new UserSyn();
bw.write(ib.doBusiness(condition));
bw.flush();
socket.shutdownOutput();
} catch (IOException e) {
e.printStackTrace();
} catch (ConditionFormatException e) {



为什么有时候服务器执行到 bw.flush();时说socket关闭,没人关过socket啊??是不是和客户端发送完数据socket.shutdownOutput();有关???
sagezk 2008-07-15
  • 打赏
  • 举报
回复
落下了:4. 如果想通知读取方数据已全部发完,你不用在那儿等了(即使数据接收方的 readxxx 出现上面的流结束标志),可以将发数据方的输出流关闭掉,使用 Socket.shutdownOutput()。
sagezk 2008-07-15
  • 打赏
  • 举报
回复
1. 读不出数据并不代表着流读到结尾了,读到流结尾的唯一标志是 readxxx 方法返回 -1 或 null 或抛出 EOF 异常等。
2. 你的程序卡在那儿是因为线程被 IO 操作阻塞了,也就是流还没读到结尾,但现在没有可马上读出来的数据(想想如果数据是动态生成的情况,数据还没生产出来,但这时你还要读数据,那你只好等待一会才能读出数据),此时读取操作(也就是对 readxxx 方法的调用)会阻塞(暂停)在那儿,等待数据生产出来。
3. avaliable() 方法的作用是看看有多少个字节的数据可马上读出来而不至于使读的操作被阻塞。相当于看看数据现在的库存有多少。
胡矣 2008-07-15
  • 打赏
  • 举报
回复
服务器端将查询结果以xml形式返回给客户端

得到一个xml
那为什么不解析xml
而要
String ling;
while((line = br.readLine())!=null){
.......
}
这样做呢?

实在不行 可以把文件先传过来放到硬盘上在读吧

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧