刚刚看关于文件上传的课程,记录自己对于read方法阻塞的理解。如有问题,希望大家指正。

read方法调用后,会阻塞(程序暂停在read方法使用处)。
阻塞后,read方法有多种情况会解除阻塞:

情况如下:

1.检测到有输入数据可用。
	一般在使用中,OutputStream.write(),InputStream.read()一一对应,
	不会出现阻塞
  2.接收到结束标记
	A.调用socket类的方法//void shutdownOutput() 禁用此套接字的输出流。  
	  可以在输出流后加上结束标记,使得输入流使用read()函数不会阻塞。
	B.FileInoutStresm的read() 在输入文件时,文件末尾自带结束标记。
  3.发送的对象被释放(不会报错)
	输出流被释放,输入流的read()会返回-1 ,不会阻塞
  4.与发送方断开连接(会报错)
	譬如:服务器被关闭,客户端的read()会因报错而停止

贴一下我遇到阻塞的代码及阻塞原因
原因:while会一直调用read,read在收不到数据后就会阻塞,不会返回-1

//IPS 是InputStream 对象
while( (len= IPS.read(bytes))!=-1) {
		//7.fos是FileOutputStream对象  将接收的数据导入硬盘
			fos.write(bytes,0,len);
		}

下面是对程序的分析

整个程序中上述阻塞代码相同形式有三处。客户端有两处,服务器一处。
三处只有服务器的那一部分会产生阻塞。
客户端第一处:是对文件的输入,文件读取完会返回-1.
客户端第二处:服务器程序的资源释放后,read()返回-1
服务器处:在客户端程序输出完文件数据后,加上shutdownOutput() ,
         人为加上结束标记,解决问题。

服务器程序main函数

public class FileUoloadServer {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		//1.创建一个服务器serversocket对象,和系统指定的端口号
		ServerSocket sever = new ServerSocket(7777);
		//2.使用serversocket对象中的accept方法,获取获取客户端请求的socket
		Socket socket = sever.accept();
		//3.使用socket对象中的方法getInputStream() 获取网路字节输入流InputStream对象
   		InputStream IPS = socket.getInputStream();
		//4.判断文件夹是否存在,不存在就创建
   		File file = new File("d:\\upload");
   		if(!file.exists()) {
   			file.mkdir();
   		}
   		//5.使用本地字节输出流fileoutputstream对象,构造方法绑定输出路径
		FileOutputStream fos = new FileOutputStream(file+File.separator+"fileUpload.JPG");
   		//6.使用网络字节输入流InputStream对象中的方法read,读取客户端上传的文件
		int len =0;
		byte[] bytes = new byte[1024];
		while( (len= IPS.read(bytes))!=-1) {
		//7.使用本地字节输出流fileoutputstream对象中的write方法,把读取的文件保存到服务器硬盘上
			fos.write(bytes,0,len);
		}
		//8.使用socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
		//9.使用网络字节输出流OutputStream对象中的的方法write,给客户端发送数据。
		OutputStream OPS = socket.getOutputStream();
		OPS.write("上传成功".getBytes());
		//10.释放资源(serversocket/socket/fileoutputstram)
		sever.close();
		socket.close();
		fos.close();
	}

}

客户端main函数

public class FileUploadClient {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		//1.创建一个本地字节输入流fileinputstream对象,构造方法绑定文件
		FileInputStream fis = new FileInputStream("E:\\fileUoload.JPG");
		//2.创建一个客户端socket对象,构造方法绑定服务器的ip和端口
		Socket soc = new Socket("127.0.0.1",7777);
	 	//3.使用socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
		OutputStream OPS = soc.getOutputStream();
		//4.使用本地字节流fileinputstream对象中的read,读取本地文件
		int len = 0;
		byte[] bytes = new byte[1024];
		while( (len= fis.read(bytes))!=-1)
		{
			//5.使用网络字节输出流OutputStream对象中的的方法write,把读取的文件上传给服务器。
			OPS.write(bytes,0,len);
			
		}
		//void shutdownOutput() 禁用此套接字的输出流。  
		soc.shutdownOutput();
		//6.使用socket对象中的方法getInputStream() 获取网路字节输入流InputStream对象
		InputStream IPS = soc.getInputStream();
		while( (len= IPS.read(bytes))!=-1)
		{
			//7.使用网络字节输入流InputStream对象中的方法read,读取服务器回写的数据
			System.out.println(new String(bytes,0,len));
		}
		//8.释放socket fileinputstream
		fis.close();
		soc.close();
	}

}