Java的Socket实现客户端和服务端上传文件

使用Java在服务端和客户端之间传送文件

此文记录了小白在实现一个简单的由客户端上传文件至服务端遇到的坑和解决办法

  • 需求描述

    • 实现客户端发送文件到服务端
    • 当文件发送完成之后由服务端发送反馈给客户端,内容是“文件上传成功!”
  • 具体问题(坑)

    • 当客户端向服务端发送文件之后,客户端可以将文件读完并成功执行后续代码,但是服务端一直无法向下执行,从而不能发送反馈给客户端
  • 实现代码如下,在代码里有详细的执行解释:
    服务端:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * ClassName: UpLoadFile
 * Author: Roohom
 * Function:文件接收服务端
 * Date: 2020/8/3 20:22
 * Software: IntelliJ IDEA
 */
public class FileRecServer {
    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(9999);
            Socket server = ss.accept();

            System.out.println("已连接的客户端IP为:" + server.getInetAddress());

            InputStream input = server.getInputStream();

            //本第流,写文件
            OutputStream os = new FileOutputStream("RecData.txt");

            Thread.sleep(100);
            byte[] buf = new byte[1024];
            int len;
            while ((len=input.read(buf))!=-1)
            {
                os.write(buf,0,len);
            }

            OutputStream output = server.getOutputStream();
            output.write("服务端的回复:上传成功!".getBytes());

            //释放资源
            os.close();
            input.close();
            output.close();
            ss.close();
            server.close();

        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

客户端:

import java.io.*;
import java.net.Socket;

/**
 * ClassName: UpLoadClient
 * Author: Roohom
 * Function:文件上传客户端
 * Date: 2020/8/3 20:23
 * Software: IntelliJ IDEA
 */
public class UpLoadClient {
    public static void main(String[] args) {
        try {
            Socket client = new Socket("192.168.1.104", 9999);
            OutputStream output = client.getOutputStream();

            //本地流,本地读文件
            InputStream is = new FileInputStream("data.txt");

            System.out.println("开始上传...");
            int len =-1;
            byte[] buf = new byte[1024];

            while ((len = is.read(buf))!=-1)
            {
                //对服务端写文件
                output.write(buf,0,len);
                System.out.println("客户端上传中...");
            }
            /*关键代码开始*/
            //不关闭客户端的输出流则会导致服务端一直阻塞
            //当客户端读到-1时,就没进入循环,所以-1就没写到服务端,故服务端就接收不到-1,所以一直不能停止循环,陷入等待客户端的状态
            client.shutdownOutput();
            /*关键代码结束*/
            is.close();
            //接收服务端的反馈
            InputStream input = client.getInputStream();
            byte[] newBuf = new byte[1024];
            int length = input.read(newBuf);
            String newStr = new String(newBuf,0,length);
            System.out.println(newStr);

            //释放资源
            is.close();
            input.close();
            output.close();
            client.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 问题分析:
    • 在客户端上传文件时,使用的是
      int len = -1;
      byte[] buf = new byte[1024];
      
      while ((len = is.read(buf))!=-1)
      {
        //对服务端写文件
        output.write(buf,0,len);
        System.out.println("客户端上传中...");
      }
      
      这种方式读文件,而在服务端也同样是这种方式读,当客户端读到-1时,就没进入循环,所以-1就没写到服务端,
      故服务端就接收不到-1,所以一直不能停止循环,陷入等待客户端的状态。所以就必须在读完文件之后,加上一句client.shutdownOutput()
      来告诉服务端已经把数据读完了。
直接知道结果
- 在客户端读完文件后加上语句`client.shutdownOutput()`      

当然还有别的解决办法,此解决办法只是这种写法的一种记录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值