java使用tcp协议时,客户端和服务端都有一个输入流和输出流.但是当需要通过这个流来传输多种信息的时候,比如传文件时先传文件名,再传文件内容,单从流本身来看是无法知道从流中读取多少字节是文件名,多少字节是文件内容.
曾经试过在服务端传送文件名时,自己在后面加一个换行符'\n',然后客户端用BufferedReader把输入流(命名为is)封装,然后调用它的readline方法,就可以成功读出文件名,但是同时通过BufferedReader和is本身来读取字节流中内容时,很容易出错.我猜想是因为同时通过两个方式来读取同一个流,有可能是流的位置指针并不会同步把...所以后来我就完全用is来读取流中的内容了.
自己写一个readline函数
private String readline()
{
//这个类就跟StringBuffer作用类似,可以动态的扩展字节数组的大小
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
byte[] b = new byte[1];
while(-1 != (is.read(b)))
{
if(b[0] == '\n')
break;
else
baos.write(b);
}
if(baos.size() == 0)
return null;
return new String(baos.toByteArray());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
能从流中读取一行出来,当然还需要往流中写一行进去
private void writeLineToServer(String s) throws IOException {
StringBuffer sb = new StringBuffer(s);
sb.append("\n"); //\n的作用相当于分隔符
os.write(sb.toString().getBytes());
}
还有一个,从流中读取一定数量的字节,用byte[]返回
public byte[] readBytes(int count)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//这里注意不能直接new byte[count],因为可能跟输入流的缓冲大小有关,如果count大于缓冲区大小,则缓冲区直接会被读空而返回,但实际上还有
//想读的字节没有读出来.这时整个输入流位置指针就乱了,读不到自己想要的内容了.
//所以要一点一点的读,给tcp滑动窗口进行滑动的时间
byte[] buf = new byte[1024];
int n;
try {
while(count > buf.length)
{
n = is.read(buf);
baos.write(buf, 0, n);
count -= n;
}
if(count>0)
{
buf = new byte[count];
is.read(buf);
baos.write(buf);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return baos.toByteArray();
}
我也不知道别人在使用tcp字节流来传输多种信息的时候是怎么把他们区分开的,但是我用\n做分割符还是挺好用的.上面的三个方法应该是客户端和服务端都可以用到的.