记录一个在学习过程中遇到的问题
需求:通过TCP协议从客户端上传一个文件到服务器,并给出客户端反馈文件上传成功。
代码如下:
服务端
public class TCPUploadServer {
public static void main(String[] args) throws IOException {
// 创建服务器的Socket服务
int port = 9992;
ServerSocket serverSocket = new ServerSocket(port);
// 监听客户端连接
Socket socket = serverSocket.accept();
// 封装通道内的流
BufferedReader brClient = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
// 封装文本文件
BufferedWriter bufferedWriter = new BufferedWriter(
new FileWriter("src\\main\\java\\com\\CodeDemo\\UPloadFile\\a.txt"));
String line = null;
while ((line = brClient.readLine()) != null) {
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
}
// 给出反馈
BufferedWriter bwServer = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
bwServer.write("文件上传成功");
bwServer.newLine();
bwServer.flush();
bufferedWriter.close();
socket.close();
}
}
客户端
public class TCPUploadClient{
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
String ip = "127.0.0.1";
int port = 9992;
Socket socket = new Socket(ip, port);
// 封装文本文件
BufferedReader bReader = new BufferedReader(
new FileReader("src\\main\\java\\com\\CodeDemo\\adu2\\c.txt"));
// 封装通道内流
BufferedWriter bWriter = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
String line = null;
while ((line = bReader.readLine()) != null) {//阻塞
bWriter.write(line);
bWriter.newLine();
bWriter.flush();
}
socket.shutdownInput();
// 接收反馈
BufferedReader brClient = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String client = brClient.readLine();//阻塞式
System.out.println(client);
// 释放资源
bReader.close();
socket.close();
}
乍一看,没有任何问题
依次运行服务端和客户端,得到反馈如下
客户端报错信息,指向了接收反馈代码块的获取输入流
这里提示输入流已经关闭了。
然后再看服务端报错
根据行次,可以看出,报错信息停在了,循环判断的这一行,循环没有退出,但无法读取到下一行,阻塞了
经过多方面的调试,之后发现问题出在shutdownInput() 这个方法,官方API解释如下
shutdownInput():Places the input stream for this socket at "end of stream",socket输入流置于流末尾
当我们在客户端执行socket.shutdownInput()后,客户端socket的输入流关闭了
实际需要关闭的是输出流,发送给服务器,代表我结束了,需要服务端退出循环。
于是修正客户端代码
public class TCPUploadClient{
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
String ip = "127.0.0.1";
int port = 9992;
Socket socket = new Socket(ip, port);
// 封装文本文件
BufferedReader bReader = new BufferedReader(
new FileReader("src\\main\\java\\com\\CodeDemo\\adu2\\c.txt"));
// 封装通道内流
BufferedWriter bWriter = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
String line = null;
while ((line = bReader.readLine()) != null) {//阻塞
bWriter.write(line);
bWriter.newLine();
bWriter.flush();
}
/*修改*/
socket.shutdownOutput();//关闭输出流
// socket.shutdownInput();//之前我把Input给关闭了,导致后面接收反馈时,提示Socket input is shutdown
// 接收反馈
BufferedReader brClient = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String client = brClient.readLine();//阻塞式
System.out.println(client);
// 释放资源
bReader.close();
socket.close();
}
再次运行
正常给出反馈