通过WAN发送文件卡住(Java Socket)

时间:2018-04-17 21:56:06

标签: java sockets client-server lan wan

通过使用java Socket在Internet上发送文件,我遇到了一个非常奇怪的问题。我有一个在LAN中工作得很好的Java服务器,它可以传输和传输文件。 问题在于WAN:当我在远程PC上运行服务器时,客户端可以与服务器通信,但是当它尝试将文件发送到服务器时,他将停留在0%。它通常发生在大文件(> = 100 MB)上,但有时也会发生在小文件中。

请有人帮助我:),谢谢。

服务器接收代码:

public void ReceiveFile(int fileSize, Socket sock, String fileName, String cmrId, PrintWriter pw){
    folderCheck(cmrId);
    FileOutputStream fos= null;
    BufferedOutputStream bos= null;
    try {
        int ret;
        int bytesRead=0;
        fos= new FileOutputStream(cmrId+"/"+fileName);  //receive file to User Dedicated folder
        bos= new BufferedOutputStream(fos);
        //InputStream input= sock.getInputStream();
        byte[] bytesArray= new byte[fileSize];
        DataInputStream dis= new DataInputStream(sock.getInputStream());

        ret= dis.read(bytesArray, 0, bytesArray.length);
        bytesRead= ret;
        //System.out.println("CmrFoldMan -- Received " + bytesRead + " of " + fileSize);  //debug
        while(bytesRead<fileSize){
            ret= dis.read(bytesArray, bytesRead, (bytesArray.length-bytesRead));
            if(ret>=0) bytesRead+=ret;
            //System.out.println("CmrFoldMan -- Received " + bytesRead + " of " + fileSize);  //debug
        }
        bos.write(bytesArray, 0, bytesRead);
        bos.flush();

        upHist= new UpdateHistory(fileName, fileSize, cmrId);
        upHist.update();

        daysLimit.deleteFilesLimit(fileSize, cmrId);  //delete files that exceed memory limit


    } catch (IOException ex) {
        Logger.getLogger(CmrFolderManager.class.getName()).log(Level.SEVERE, null, ex);
    }
    finally{
        try {
            fos.close();
            bos.close();
        } catch (IOException ex) {
            Logger.getLogger(CmrFolderManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

客户发送代码:

public long upload(String fileToSend){
    long uploadTimerStart = System.currentTimeMillis();  //start timer
    if(contactServerCheckError()) return -1;
    try{
        pw.println(fileSize);
        pw.println(fileName);
        Socket sendSock= new Socket(ip, filePort);   //connecting to sending file port
        DataOutputStream dos= new DataOutputStream(sendSock.getOutputStream());
        File file= new File(fileToSend);
        int arraySize= (int)file.length();  //used for println only
        byte[] array= new byte[1024];  //array is 1024 to use progress bar
        fis= new FileInputStream(file);
        bis= new BufferedInputStream(fis);
        int len;
        int tmpBytes=0;
        while((len= bis.read(array))>0){
            //System.out.println("SendFile " + tmpBytes + " bytes " + "of " + arraySize);  //debug
            dos.write(array, 0, len);
            dos.flush();
            tmpBytes+=len;
            updateProgressBars(tmpBytes);
            updateLabelsPercentage(tmpBytes);
        }

    } catch (FileNotFoundException ex) {
        Logger.getLogger(SendFile.class.getName()).log(Level.SEVERE, null, ex);
        return -1;
    } catch (IOException ex) {
        Logger.getLogger(SendFile.class.getName()).log(Level.SEVERE, null, ex);
        return -1;
    }
    finally{
        try{
        if(bis!=null) bis.close();
        if(os!=null) os.close();
        //if(sock!=null) sock.close();
        } catch (IOException ex) {
            Logger.getLogger(SendFile.class.getName()).log(Level.SEVERE, null, ex);
            JOptionPane.showMessageDialog(null, "ERROR " + ex);
            return -1;
        }
    }

    long uploadTimerEnd = System.currentTimeMillis();  //end timer
    long uploadTimerDelta= uploadTimerEnd - uploadTimerStart;
    return uploadTimerDelta;
}

1 个答案:

答案 0 :(得分:0)

嗯......对于初学者......据我所知,在接收代码中,您正在创建一个与目标文件大小相当的字节数组,

byte[] bytesArray= new byte[fileSize];

并继续读取输入流,进入字节数组,直到它已满,

while(bytesRead<fileSize){
        ret= dis.read(bytesArray, bytesRead, (bytesArray.length-bytesRead));

然后你一次写到文件

bos.write(bytesArray, 0, bytesRead);

对于100MB文件,如您所述,这意味着您在内存中保留100MB。这不是......一个好主意。

fos= new FileOutputStream(cmrId+"/"+fileName);
InputStream is = sock.getInputStream());

int read = 0;
byte[] buf = new byte[1024];
while( (read = is.read(buf)) != -1) {
    fos.write(buf, 0, read);
}

上面的代码抛弃了你正在使用的DataInputStream(据我所知,它没有添加任何内容),一次读取最多1024个字节,并将其以块的形式写入FileOutputStream,而不会在内存中保存超过一千字节。试一试,看看它是否更可靠。