TCP通信中的readLine()
Server.java
ServerSocket ss=new ServerSocket(10086);
Socket s=ss.accept();
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
// 封装目的地文本文件
BufferedWriter bw=new BufferedWriter(new FileWriter("copy.java",true));
String line =null;
// 读取客户端数据并将其写入文本文件
while((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
bw.flush();
}
// 提供一个反馈表示文件上传成功
BufferedWriter bwServer=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bwServer.write("文件上传成功!");
bwServer.flush();
bwServer.close();
Client.java
BufferedReader br=new BufferedReader(new FileReader("InterfaceTest.java"));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line =null;
// 读取客户端文件的数据
while((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
bw.flush();
}
// 接受反馈
BufferedReader brClient=new BufferedReader(new InputStreamReader(s.getInputStream()));
String Client=brClient.readLine();
System.out.println(Client);
brClient.close();
在TCP通信的实例中,向服务器端上传一个文件,当上传完成时,想让服务器给我一个反馈“文件上传成功!”,但是会发现一个问题:文件能上传成功,但是反馈一直接收不到,程序为堵塞状态!
发现是readLine()的问题:分为两种情况
-
在文本文件格式下:
读取一个文本行。当读取到“\r”或者"\n"才会返回结果,返回的结果中并没有(\r ,\n)。这就是读取一行的意思。什么时候返回null呢?当读取到文件末尾的时候才会返回null!(这里和通信过程中的readLine不一样)
-
Socket通信中:
在TCP通信中,我想要的是服务器读取完文件给我一个反馈,但是这里当服务器读取完数据后,并不会返回NULL,也是就说吧,无法跳出while循环,他会一直堵塞在这!实际上readLine()是一个阻塞函数,当数据读取完之后他不会返回null!为什么? **因为这里readLine()读取的并不是文本文件!**它读取的是通道(TCP通信必须先建立通道)中的流数据
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
所以它并不会返回NULL,br不知道已经没有数据,br会一直等着客户端发送数据,但是客户端数据已经发送完毕,等着服务器给反馈,两个相互等待!
如何解决?
shutdownOutput(),在Client.java中的while循环后面调用此方法!
public void shutdownOutput()throws IOException
禁用此套接字的输出流。对于 TCP 套接字,任何以前写入的数据都将被发送,并且后跟 TCP 的正常连接终止序列。 如果在套接字上调用 shutdownOutput() 后写入套接字输出流,则该流将抛出 IOException。
这里的终止序列(-1)告诉Server中的输入流,已经没有数据了,(readLine读到这里返回null)这样server才会继续下面的操作!
关于shutdownOutput方法
Client
s.shutdownOutput();
System.out.println(s.isOutputShutdown());//true
System.out.println(s.isConnected());//true
Server
System.out.println(s.isOutputShutdown());//false
System.out.println(s.isConnected());//true
上面的代码表示:
- 关闭是单向性的!(Client调用的并不会影响到Server)
- 只关闭流对象,并不会关闭Socket连接(close全部关闭)