在做网络通信时,我们在关闭链接时是选择Socket.close()还是OutputStreamWriter.cloer()?
如果使用Socket.close().会导致数据的丢失的。
看看官方文档上的解释:
Socket.close()
Any thread currently blocked in an I/O operation upon this socket will throw a SocketException
.
Once a socket has been closed, it is not available for further networking use (i.e. can't be reconnected or rebound). A new socket needs to be created.
Closing this socket will also close the socket's InputStream
and OutputStream
.
If this socket has an associated channel then the channel is closed as well.
关闭socket.
再次socket基础上阻塞的所有输入输出操作会抛出异常。
一旦一个socket被关闭,它不可以被再次使用(比如重新连接).你需要重新创建一个socket.
关闭socket会关闭它的InputStream和OutputStream。
如果socket和一个channel有关联,这个channel也会自动关闭。
OutputStreamWriter. close()
关闭流,清空缓冲区(意思就是把缓冲区剩余的数据继续发送出去)。当流被关闭时,write()和flush()函数都会引起异常抛出。关闭一个已经关闭的流没有效果。
从官方文档可以看到,OutpuStreamWriter.close()会将缓冲区剩下的数据发送出去,那么Socket.close()呢,上面的描述中没有说它会清空缓冲区,但是有一句“关闭socket会关闭它的InputStream和OutputStream”,我们看看关闭OutputStream会不会清空缓冲区,如果不会,说明Socket.close()不会清空缓冲区。
官方文档:
OutputStream.close()
Closes this output stream and releases any system resources associated with this stream. The general contract of
close
is that it closes the output stream. A closed stream cannot perform output operations and cannot be reopened.
关闭输出流,释放所有相关系统资源。最普通的合约就是关闭输出流。一个被关闭的输出流不可以进行输出操作和重新启用。
OutputStream.close()也不会释放缓冲区的内容。
总结一下,如果你使用了OutputStreamWriter作为socket通信的组件,千万不要直接关闭socket。直接关闭socket会导致缓冲区中的数据丢失而发送不到接受者。所以建议使用OutputStreamWriter.close()。这样不会导致数据的丢失。
其实使用Socket.close() 也是可以的,但是一定要在Socket.close()之前,先使用OutputStreamWriter.flush(),发送完缓冲区内的数据。保证数据完整。
如果还是不能理解,我下面给出一个实验代码。
需要新建两个类,服务器类:Server.java,客户端类Client.java
Server.java代码:
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException
{
ServerSocket server=new ServerSocket(8002);
System.out.println("listening.....");
Socket client=server.accept();
System.out.println("accept");
InputStream is=client.getInputStream();
byte[] buf=new byte[1000];
int read;
while((read=is.read(buf))!=-1)
{
System.out.write(buf,0,read);
}
}
}
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException
{
Socket socket=new Socket("127.0.0.1",8002);
OutputStream os=socket.getOutputStream();
OutputStreamWriter osw=new OutputStreamWriter(os,"utf-8");
osw.write("a");
//第一次试验使用socket.close()
socket.close();
//第二次试验请将socket.close()注释,将下一行注释取消,采用OutputStreamWrite.close()
//osw.close();
//加上无限循环防止因为进程结束导致socket自动释放
while(true)
{
}
}
第一次:
启动Server.java,启动Client.java,发现Server.java接受不到发送的"a"。
第二次:
启动Server.java,将Client.java由socket.close()改为osw.close(),启动Client.java,发现服务端收到了发送的"a"。
实验完毕。相信大家已经能看懂了。