以下是我的一个代码
用途是读取BufferedInputStream内的数据
private String read(BufferedInputStream is)throws Exception
{
int readret=is.read();//first char
int len = is.available();
byte[] buffer = getByteBuffer(readret,len);
is.read(buffer,1,len);
return new String(buffer,"utf-8");
}因为BufferedInputStream里面是socket.getInputStream()socket类的数据 长度不定。
我目的是 通过available()方法初始一个buffer然后在读取。1. 上面的方法有问题吗?可以一次读取所有数据吗?
2. 上面的方法我在不同机器上运行了,但是结果不一样。
我都抓包看了 包内数据
一台抓包 并运行结果 可以一次读取socket内数据。
另外一台抓包 并运行 结果抓包结果可以看到完整的数据包数据,但是上面运行方法没有读全所有数据。
3. 对于我的需求 是对socket流内每次长度不一的数据进行读取有什么好方法?
有人可能说用BufferedReader. readLine() 但是网络数据内本身有的\r\n等 也是 我所需要的,需要一次读全。
用途是读取BufferedInputStream内的数据
private String read(BufferedInputStream is)throws Exception
{
int readret=is.read();//first char
int len = is.available();
byte[] buffer = getByteBuffer(readret,len);
is.read(buffer,1,len);
return new String(buffer,"utf-8");
}因为BufferedInputStream里面是socket.getInputStream()socket类的数据 长度不定。
我目的是 通过available()方法初始一个buffer然后在读取。1. 上面的方法有问题吗?可以一次读取所有数据吗?
2. 上面的方法我在不同机器上运行了,但是结果不一样。
我都抓包看了 包内数据
一台抓包 并运行结果 可以一次读取socket内数据。
另外一台抓包 并运行 结果抓包结果可以看到完整的数据包数据,但是上面运行方法没有读全所有数据。
3. 对于我的需求 是对socket流内每次长度不一的数据进行读取有什么好方法?
有人可能说用BufferedReader. readLine() 但是网络数据内本身有的\r\n等 也是 我所需要的,需要一次读全。
用ObjectInputStream也行,这个可以分"帧",每次长度可以确定
就没问题呢?
阻塞
阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。对于同 步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。例如,我们在CSocket中调用Receive函数,如果缓冲区中没有数 据,这个函数就会一直等待,直到有数据才返回。而此时,当前线程还会继续处理各种各样的消息。如果主窗口和调用函数在同一个线程中,除非你在特殊的界面操 作函数中调用,其实主界面还是应该可以刷新。socket接收数据的另外一个函数recv则是一个阻塞调用的例子。当socket工作在阻塞模式的时候, 如果没有数据的情况下调用该函数,则当前线程就会被挂起,直到有数据为止。非阻塞
非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。 对象的阻塞模式和阻塞函数调用
对象是否处于阻塞模式和函数是不是阻塞调用有很强的相关性,但是并不是一一对应的。阻塞对象上可以有非阻塞的调用方式,我们可以通过一定的API去轮询状 态,在适当的时候调用阻塞函数,就可以避免阻塞。而对于非阻塞对象,调用特殊的函数也可以进入阻塞调用。函数select就是这样的一个例子。
而是指在没有阻塞前还可以读取多少数据,也就是这一个数据包对方发送了多少数据。而在Socket发送过程,对方发送的数据是会自动分包的,这个过程不受你控制。
所以Socket流来说,双方必须先协议总共发送多少字节的数据,再读取指定长度的数据而不用理会available
这样设计思路来读取数据正是API是最反对的。
1)上面的方法有问题吗?可以一次读取所有数据吗?
问题很严重。不要这样来设计程序。能否一次读取所有数据,完全看网络的通信繁忙程度,因而这样设计是不对的。
2)上面的方法我在不同机器上运行了,但是结果不一样。
不用抓包,都能知道肯定结果是不定的(即:结果有时相同,有时不一样)
3) 对于我的需求 是对socket流内每次长度不一的数据进行读取有什么好方法?
这是一个最基本的网络读取数据的要求,显然楼主是刚入这一行的,对网络通信不熟悉。
通用的做法(也是网络上最常用的做法是)以网络字节流读取为例:
你首先与服务器方规定好一个应用层的协议(这是任何网络应用程序在设计之前,首先要做的事)
针对你的需求,不妨规定(简单些):4个字节表示本次传输的字节长度后跟真正的字节数据
读取时,你先读4个字节的那个长度,然后再这个长度反复多次读取,直到读到指定个数的字节为止。为加快
读取性能,可用每次带绥中的流带读(如:缓冲区8K字节)
3) 对于我的需求 是对socket流内每次长度不一的数据进行读取有什么好方法?的解答
判断 一套服务器回应数据 是否完整的话
就要 每次将8K(如您所说)接起来然后 判断?因为 每次数据都长度不一
byte[] buf=new byte[100];
int len=is.read(buf);
System.out.println(new string(buf,o,len));不用缓存试一试!呵呵!刚学这个!试着回答赚点分!
如果用缓存
InputStream is=new InputStream();
BufferedInputStream bis=new BufferedInputStream(is);
晕下课了!~~过下来补充缓存这的~做个标记~
我的意思是说:为加快网络通信计取速度,通常都用带缓冲的流(如:8K)去读,这是应该这样做的。
如何去读呢?代码怎样写?
很简单:假设是按照上述的应用层协议的约定,则:
DataInputStream dis=new DataInpuStream(你的那个8K带缓冲的BifferedInputStream);
先读长度:
int len=dis.readInt();//4个字节的长度
然后一个while循环,反复用int hasRead=dis.read(buf),每次累加hasRead[它表示本次读了多少个字节到buf数组中了]直到读到len个字节为止。
就行了。
DataInputStream dis=new DataInpuStream(is);
int len=dis.readInt();
int hasRead=0;
while(true)
{
if(hasRead!=len)
{
int hasRead=dis.read(buf);
hasRead+=hasRead;
}
else
break;
}