除非我调用os.close(),否则不会收到文件

时间:2014-08-26 10:19:39

标签: java sockets fileinputstream fileoutputstream

我使用java套接字编程将文件从服务器发送到客户端。 这是我的服务器端代码:

public void fileSendingProtocol(String filePath) {

    File myFile = new File(filePath);
    byte[] mybytearray = new byte[(int) myFile.length()];

    FileInputStream fis = null;

    try {
        fis = new FileInputStream(myFile);
    } catch (FileNotFoundException ex) {
        System.err.println(ex);
    }
    BufferedInputStream bis = new BufferedInputStream(fis);

    try {

        bis.read(mybytearray, 0, mybytearray.length);
        os.write(mybytearray, 0, mybytearray.length);
        os.flush();
        System.out.println(filePath + " Submitted");
        // File sent, exit the main method
    } catch (IOException ex) {
        // Do exception handling
        System.out.println(ex.toString());
    } finally {
        try {
            os.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

这里我已经关闭了finally块中的操作系统。因为如果我省略os.close(),那么我无法在客户端收到该文件。 这是我的客户端文件接收代码:

 public static void fileReceivingProtocol(String filePath) {

    try {
        fos = new FileOutputStream(filePath);
    } catch (FileNotFoundException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    bos = new BufferedOutputStream(fos);
    /* read question paper from the server. */
    try {       

        bytesRead = is.read(aByte, 0, aByte.length);

        do {
            baos.write(aByte);
            bytesRead = is.read(aByte);         
        } while (bytesRead != -1);
        bos.write(baos.toByteArray());
        bos.flush();
        fos.close();            

    } catch (IOException e) {
        System.err.println("IOException:  " + e);
    }

}

我需要服务器先发送一个文件。然后,在收到该文件后,客户端需要在几分钟后将另一个文件发送到服务器。但是,如果我在服务器端调用os.close(),那么我的套接字将被关闭,之后我无法继续进行任何进一步的通信。

1 个答案:

答案 0 :(得分:4)

您无需关闭osOutputStream),只需调用其flush()方法即可。出于性能原因,流通常是缓冲的。对flush()的调用将指示实现发送所有缓存数据。

您发送的文件很可能很小(最多可能是几KB),这比典型的缓存大小要小。如果您写的数据少于缓存大小(或者Socket OutputStream的情况下可以在TCP数据包中传输的数据),则实施可能不会将其发送给一段时间flush()将发送缓存的任何数据。

如果您的客户端不知道文件大小(不知道要等待多少字节),您必须实现某种"协议"交换这些信息。一个非常基本的方法是首先以4个字节(即Java int的大小)发送文件大小(字节数),然后发送文件的内容。 客户端将知道前4个字节将是文件大小,它将等待/读取该字节数。

如何将int转换为字节:Convert integer into byte array (Java)Java integer to byte array

修改过的文件发件人

// First write the file's length (4 bytes)
int length = (int) myFile.length();
os.write((length >>> 24) & 0xff);
os.write((length >>> 16) & 0xff);
os.write((length >>>  8) & 0xff);
os.write(length & 0xff);

// And now send the content of the file just as you did

修改文件接收器

// First read the file's length (4 bytes)
int b1 = is.read();
int b2 = is.read();
int b3 = is.read();
int b4 = is.read();
if (b1 < 0 || b2 < 0 || b3 < 0 || b4 < 0)
    throw new EOFException(); // Less than 4 bytes received, end of stream
int length = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;

// And now read the content of the file which must be exactly length bytes