java通过TCP字节流传输和读取数据

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做分割符还是挺好用的.上面的三个方法应该是客户端和服务端都可以用到的.




你可能感兴趣的:(java学习)