[疯狂Java]TCP:半关闭Socket

1. 怎样表示输入或输出的结束:

    1) 都知道TCP通信其实就是用客户端(Socket对象)的socket传递数据的,传递数据都是通过Socket类获取InputStream和OutputStream的;

    2) 一般最纠结的就是不知道对方的输出什么时候结束,前面给出的示例都没有处理输出结束(对方)的问题,除非你直接关闭程序否则输出永远都不会结束;

    3) 都知道只要关闭输出流就表示输出结束,但是在Socket通信中,一旦输出流被彻底关闭就意味着Socket的关闭,那么网络通信就无法继续了,通常希望关闭输出流之后输入流还可以继续从远程接受数据,或者关闭输入流之后还能通过输出流向远程传送数据;

    4) 因此Socket类提供了半关闭的方法:

         i. void shutdownOutput(); // 只关闭输出流(但输入流仍然能用)进入半写状态(write-half),通知对方远程输出已经关闭,

         ii. void shutdownInput(); // 只关闭输入流(但输出流仍然能用)进入半读状态(read-half),通知对方远程读取已经关闭

!!即使先后调用这两个方法也不会关闭Socket,只不过处于既不能输出也不能输入的废物状态;

!!!上面的方法是半关闭方法,那么彻底关闭输出输入流应该怎么做呢?

            a. 通常会对Socket对象调用getInputStream、getOutputStream然后用BufferedReader、PrintStream等包装;

            b. 那个包装器就是彻彻底底的输入输出流了,如果调用包装器对象br、ps的close方法那就彻底的关闭输入输出流了;

            c. 它们的关闭就意味着Socket也被关闭了!!

!!检查Socket对象是否关闭的方法:boolean Socket.isClosed();

    5) 同样Socket类也提供了查看是否处于半读半写状态的方法:

         i. boolean isOutputShutdown(); // 是否处于半写状态

         ii. boolean isInputShutdown(); // 是否处于半读状态


2. 半关闭适用于哪些场景:

    1) 当然是用于那些不需要长久保持通信状态的一站式服务;

    2) 特别适用于HTTP通信,而且特别适用于客户端,因为客户端在发送请求后就无需再发送其它数据了,往往只是等待服务器端返回想要的资源;

    3) 因此在客户端发送完请求之后就可以立马半关闭输出流了(半写状态);


3. 示例:

public class Server {
	
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		ServerSocket ss = new ServerSocket(30000);
		Socket s = ss.accept();
		PrintStream ps = new PrintStream(s.getOutputStream());
		Scanner scan = new Scanner(s.getInputStream());
		
		ps.println("first line");
		ps.println("second line");
		
		s.shutdownOutput(); // 如果是ps.close()那么s也就关闭了
		System.out.println(s.isClosed()); // false
		
		while (scan.hasNextLine()) {
			System.out.println(scan.nextLine()); // 有输出,说明半关闭
		}
		
		scan.close();
		s.close();
		ss.close();
	}

}


你可能感兴趣的:(tcp,疯狂Java,半关闭Socket)