EOFException或SocketException:当通过套接字传输文件时,Socket被关闭

时间:2013-10-28 12:02:12

标签: java sockets

我正在开发一个客户端和服务器之间的简单文件传输应用程序。 这是我的代码: 我的客户(发件人):

try{
                File file_sender=XMLParser.register(peername, address, port, listfile);
                int count;
                byte[] buffer = new byte[1024];
                int len=(int) file_sender.length();
                byte[] mybytearray = new byte[len];     
                DataOutputStream output=new DataOutputStream(Info.connection.getOutputStream());
                output.writeInt(len);
                System.out.println(len);
                BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file_sender));
                bis.read(mybytearray, 0, len);
                output.write(mybytearray, 0, len);
                bis.close();
                output.close();
               // Info.connection.close();
            }catch(Exception ex){
                System.out.println(ex.toString());
            }

我的服务器(接收方):

public class IOThread extends Thread {
private Socket connection;
private DataInputStream input;
public IOThread(Socket connection) throws IOException{
    this.connection=connection;
    input=new DataInputStream(connection.getInputStream());

}
@Override
public void run(){
    while(true){
        try{
            int filesize=12022386;
            int bytesRead;
            int currentTot = 0;
            byte[] bytearray = new byte [filesize];
            int len=input.readInt();
            FileOutputStream fos = new FileOutputStream("data.xml");
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            bytesRead=input.read(bytearray, 0,bytearray.length);
            System.out.println(len);
            currentTot=bytesRead;
            do{
                bytesRead=input.read(bytearray, currentTot, (bytearray.length-currentTot));
                if(bytesRead>=0) currentTot+=bytesRead;
                System.out.println("pos: "+currentTot);
            } while(len!=currentTot);
            bos.write(bytearray, 0, currentTot);
            bos.close();
            //connection.close();
            System.out.println("Done");
        }catch(EOFException ex){
            System.out.println(ex.toString());
            break;
        }catch( Exception ex){}
    }
}

我想传输多个文件,所以我不想关闭套接字。因此,我使用变量“len”来检查文件是否完全转移。

如果我在发送文件后关闭“输出”,那么服务器会抛出EOFException并且文件发送成功。

当我不关闭输出时,服务器无法接收文件成功。但是Server不会抛出EOFException。

你可以帮我解决这个问题吗? 更新:如果我没有在客户端关闭变量“output”,那么这是我在控制台屏幕上的输出:

246

pos:496

感谢。 抱歉我的英语不好

4 个答案:

答案 0 :(得分:2)

两件事:

首先,您似乎忽略了接收代码中的文件长度?你有:

        int filesize=12022386;
        int bytesRead;
        int currentTot = 0;
        byte[] bytearray = new byte [filesize];
        int len=input.readInt();

无论len的值是什么,您都在调整bytearray的大小为12022386字节,并且您要求输入流中的那么多字节。

其次,当您关闭输出流时,任何尚未写入的缓存/缓冲数据都会自动刷新(例如,在您的情况下,发送到服务器)。

当您完成发送第一个文件以强制它完成将所有数据发送到服务器时,显式刷新输出流。然后,您可以继续将该输出流用于其他事项。

传输完成后,在发送代码中执行output.flush()

答案 1 :(得分:2)

问题是你读取的文件超出了文件大小,即不是读取len个字节,而是读取bytearray.length个字节,这个字节更大。

因此,您阅读的时间超过len字节,因此永远不会满足len!=currentTot,因为您可以从示例输出中看到currentTot == 496len == 246。< / p>

在while循环中进行以下更改:

do{
   bytesRead=input.read(bytearray, currentTot, (len - currentTot));
   if(bytesRead>=0) currentTot += bytesRead;
   System.out.println("pos: " + currentTot);
} while(len != currentTot);

为了确保您不会因为类似错误而无休止地循环,您可以使用currentTot < len代替len != currentTot作为您的条件。

此外,由于您已经在使用DataInputStream,请考虑使用readFully读取套接字内容。这将阻塞,直到从套接字读取给定数量的字节,从根本上消除了对while循环的需要。阅读更多here

答案 2 :(得分:2)

抛弃所有循环并在发送文件后使用DataInputStream.readFully();关闭套接字;不要结束文件长度;并使用正常大小的缓冲区,比如说8192字节。

答案 3 :(得分:0)

您的BufferedOutputStream填充似乎不正确。下面的代码必须在while循环中。

bos.write(bytearray, 0, currentTot);

尝试这样的事情:

BufferedOutputStream buffOut=new BufferedOutputStream(fos);
byte []arr = new byte [1024 * 1024];
int available  = -1;
while((available = buffIn.read(arr)) != -1) { 
    buffOut.write(arr, 0, available); 
}      
buffOut.flush();
buffOut.close(); 

再次测试。

编辑:用@Jason的正确评论更新了我的答案。