http://blog.csdn.net/dabing69221/article/details/17351881
前言:
在Java Socket中提供了2中关闭方法,其中包括:close() 、shutdownOutput()/shutdownInput() ,前一段时间做项目中用到了Socket,但是没有好好总结。
现在,我把我遇到的问题分享一下:
在网络协议中,通常明确指定了由谁来发起 “关闭”连接。
例如:在HTTP协议中,客户端先向服务端发送一个请求,然后服务器响应请求的信息。由于客户端不知道服务端响应信息的大小,因此服务器必须通过关闭套
接字来指示响应信息结束 —— 这个就是由服务器端发起的关闭连接!
一. Socket.close()方法
这个方法我们估计都不会陌生,一般使用完Socket后,都会调用Socket.close() 来释放相关的资源。当我们调用Socket.close()方法将同时终止两个方向(输入
和输出)的数据流。一旦一个终端(客户端或服务端)关闭了套接字,它将无法再发送或接收数据。这就意味着close( )方法只能在调用者完成了通信之后用来
给另一端发送信号。只要服务端收到了客户端的关闭信号,就立即关闭连接。
1. 考虑一个场景:
假设你有一个服务器,接收到消息后,在发回给客户端,这种情况下应该是有哪一端来关闭连接呢?
由于从客户端发送的消息长度是任意的,客户端需要关闭连接以通知服务器消息发送完毕,那么客户端应该什么时候调用close( )方法呢,如果客户端在发送完最后
一个字节后立即调用close( )方法,它将无法接收服务器发送的消息 (因为: 关闭此套接字也将会关闭该套接字的 InputStream
和 OutputStream
);如果客户端在接收
完所有的数据后在调用close ( )方法,那么服务端 将不知道到底有多少数据要接收(因为:客户端的输出流一直没有关闭,所以,服务端的输入流也就无法到达流末尾返回-1),
所以,服务器在接收数据时就一直阻塞,而这个时候客户端又要等待接收服务端发送来的消息(即使服务端发送了消息,但因为服务端的输出流一直没有关闭,所以,
服务端的输入流也就无法到达流末尾返回-1,所以客户端在接收数据时就一直阻塞) —— 以上问题就造成:”服务端和客户端都在接收数据时阻塞"
情况一 :客户端在发送完最后一个字节后立即调用close( )方法
- //服务端
- public class Server
- {
- public static void main(String[] args) throws IOException
- {
- System.out.println("------------------------------------");
- System.out.println("Server start......");
- System.out.println("------------------------------------");
- ServerSocket server = new ServerSocket(8888);
- while (true)
- {
- Socket client = server.accept();
- OutputStream out = client.getOutputStream();
- InputStream in = client.getInputStream();
- ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
- byte[] temp = new byte[1024];
- int realLen = 0;
- while ((realLen = in.read(temp)) != -1)
- {
- byteArrayOut.write(temp, 0, realLen);
- }
- byte[] recv = byteArrayOut.toByteArray();
- // 将接收的消息,发回给客户端
- out.write(recv);
- out.flush();
- }
- }
- }