当前位置: 首页 > 面试题库 >

连接断开后恢复文件上传/下载(套接字编程)

司空海荣
2023-03-14
问题内容

我正在编写一个程序,使用套接字编程在客户端和服务器之间下载/上传文件。到目前为止,我编写的代码在一定程度上可以正常传输文件。但是,如果在进行下载/上载时由于网络/客户端/服务器中的问题导致连接失败。.我需要从原始点恢复下载/上载(不希望重新发送原始发送的数据)。我不确定该怎么做。我正在将文件读入字节数组并通过网络发送。我最初的想法是每次下载时..我应该检查文件是否已存在并将数据读入字节数组->将数据发送到服务器进行比较,然后通过以下方式返回服务器文件中的剩余数据:比较两个字节数组。但这似乎效率低下,并且取消了继续下载的意义(因为我再次发送了数据)。注意:文件名是唯一标识符。如果有人可以给我有关如何实现文件恢复html" target="_blank">功能的建议,我将不胜感激。

Server side code:
    package servers;
    import java.io.*;
    import java.net.*;
    import java.util.Arrays;
    public class tcpserver1 extends Thread
    {
        public static void main(String args[]) throws Exception 
    {
        ServerSocket welcomeSocket = null;
        try
        {
             welcomeSocket = new ServerSocket(5555);
             while(true)
             {
                 Socket socketConnection = welcomeSocket.accept();
                 System.out.println("Server passing off to thread");
                 tcprunnable tcprunthread = new tcprunnable(socketConnection);
                 Thread thrd = new Thread(tcprunthread);
                 thrd.start();
                 System.out.println(thrd.getName());
             }
        }
         catch(IOException e){
             welcomeSocket.close();
             System.out.println("Could not connect...");
         }
      }
}
class tcprunnable implements Runnable
{
    Socket socke;
    public tcprunnable(Socket sc){
         socke = sc;
    }


    public void download_server(String file_name)
    {   
        System.out.println("Inside server download method");
        try
        {
        System.out.println("Socket port:" + socke.getPort());

        //System.out.println("Inside download method of thread:clientsentence is:"+clientSentence);
        // Create & attach output stream to new socket
        OutputStream outToClient = socke.getOutputStream();
        // The file name needs to come from the client which will be put in here below
        File myfile = new File("D:\\ "+file_name);
        byte[] mybytearray = new byte[(int) myfile.length()];
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myfile));
        bis.read(mybytearray, 0, mybytearray.length);
        outToClient.write(mybytearray, 0, mybytearray.length);
        System.out.println("Arrays on server:"+Arrays.toString(mybytearray));
        outToClient.flush();
        bis.close();    
    }
        catch(FileNotFoundException f){f.printStackTrace();}
        catch(IOException ie){
            ie.printStackTrace();
        }
    }

    public void upload_server(String file_name){

        try{

        byte[] mybytearray = new byte[1024];
            InputStream is = socke.getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            FileOutputStream fos = new FileOutputStream("D:\\ "+file_name);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            int bytesRead = is.read(mybytearray, 0, mybytearray.length);
                    bos.write(mybytearray, 0, bytesRead);
            do {
                baos.write(mybytearray);
                bytesRead = is.read(mybytearray);
        }
            while (bytesRead != -1);
            bos.write(baos.toByteArray());
            System.out.println("Array on server while downloading:"+Arrays.toString(baos.toByteArray()));
            bos.close();
    }
        catch(FileNotFoundException fe){fe.printStackTrace();}
        catch(IOException ie){ie.printStackTrace();}


    }

    @Override
    public void run()
    {   
        try
        {       
            System.out.println("Server1 up and running" + socke.getPort());
            //  Create & attach input stream to new socket
                BufferedReader inFromClient = new BufferedReader
                (new InputStreamReader(socke.getInputStream()));
                // Read from socket
                String  clientSentence = inFromClient.readLine();
                String file_name = inFromClient.readLine();

                System.out.println("Sever side filename:" + file_name);
                try{
                if(clientSentence.equals("download"))
                {
                    download_server(file_name);
                }
                else if(clientSentence.equals("upload"))
                {

                    upload_server(file_name);
                    System.out.println("Sever side filename:" + file_name);
                }
                else
                {
                    System.out.println("Invalid input");
                }
                }
                catch(NullPointerException npe){
                    System.out.println("Invalid input!");
                }
                    socke.close();  
        }
        catch(IOException e)
        {
            e.printStackTrace();
            System.out.println("Exception caught");
        }           
    }
}

客户端代码:

package clients;
import java.io.*;
import java.net.*;
import java.util.Arrays;
public class tcpclient1 
{   
        public static void main (String args[]) throws Exception
        {   
                // Create input stream to send sentence to server
                BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
                Socket clientSocket = null;
                while(true){
                System.out.println("Please enter the server you want to use");
                System.out.println("Enter 1 for Server 1 and 2 for Server2");
                String server_choice = inFromUser.readLine();

                if(server_choice.equals("1")){
                // Create client socket to connect to server
                // The server to use will be specified by the user
                 clientSocket = new Socket("localhost",5555);
                 break;
                }
                else if(server_choice.equals("2"))
                {
                    clientSocket = new Socket("localhost",5556);
                    break;
                }
                else
                {
                    System.out.println("Invalid entry");
                }
        }


                System.out.println("Please enter download for dowloading");
                System.out.println("Please enter upload for uploading");

            // sentence is what'll be received from input jsp   
                String sentence = inFromUser.readLine();

                if(sentence.equals("download"))
                {
                    download_client(clientSocket,sentence);
                }
                else if(sentence.equals("upload"))
                {
                    upload_client(clientSocket,sentence);
                }
                else
                {
                    System.out.println("Invalid input");
                }

            clientSocket.close();
        }

        public static void download_client(Socket clientSocket , String sentence)
        {
            try{
            // Create output stream attached to socket
            DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());

            // Send line to server
            outToServer.writeBytes(sentence+'\n');
            BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("Enter the name of file to download:");
            String file_to_download = inFromUser.readLine();


            if(searching(file_to_download))
            {

                // Read local file and send that to the server for comparison
            // DONT THINK THIS IS THE RIGHT WAY TO GO ABOUT THINGS SINCE IT BEATS THE PURPOSE OF RESUMING A DOWNLOAD/UPLOAD

            }


            // Send filetodownload to server
            outToServer.writeBytes(file_to_download+'\n');
            byte[] mybytearray = new byte[1024];
            InputStream is = clientSocket.getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            FileOutputStream fos = new FileOutputStream("E:\\ "+file_to_download);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            int bytesRead = is.read(mybytearray, 0, mybytearray.length);
            bos.write(mybytearray, 0, bytesRead);
            do {
                baos.write(mybytearray);
                bytesRead = is.read(mybytearray);
            }
            while (bytesRead != -1);
            bos.write(baos.toByteArray());
            System.out.println("Array on client while downloading:"+Arrays.toString(baos.toByteArray()));
            bos.close();    
      }
            catch(FileNotFoundException fe){fe.printStackTrace();}
            catch(IOException ie){ie.printStackTrace();}

        }
        public static void upload_client(Socket clientSocket, String sentence)
        {
                try{
                    // Create output stream attached to socket
                DataOutputStream outToServer1 = new DataOutputStream(clientSocket.getOutputStream());
                    // Send line to server
                outToServer1.writeBytes(sentence+'\n');
                    System.out.println("In the client upload method");

                    BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
                    System.out.println("Enter the name of file to upload:");
                    String file_to_upload = inFromUser.readLine();
                    //System.out.println("Cline side file name:"+file_to_upload);
                    outToServer1.writeBytes(file_to_upload+'\n');
                    System.out.println(file_to_upload);
                    OutputStream outtoserver = clientSocket.getOutputStream();

            File myfile = new File("E:\\ "+file_to_upload);
            byte[] mybytearray = new byte[(int) myfile.length()];
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myfile));
            bis.read(mybytearray, 0, mybytearray.length);
            outtoserver.write(mybytearray, 0, mybytearray.length);

            System.out.println("filename:"+file_to_upload+"Arrays on client while uploading:"+Arrays.toString(mybytearray));
            outtoserver.flush();
            bis.close();    
                }
                catch(FileNotFoundException fe){fe.printStackTrace();}
                catch(IOException ie){ie.printStackTrace();}
        }


        public static boolean searching(String file_name)
        {
            String file_path = "E:\\ "+file_name;
            File f = new File(file_path);
            if(f.exists() && !f.isDirectory()) { return true; }
            else
                return false;

        }       
       }

上面的代码可以很好地在客户端和服务器之间传输文件。
再次,非常感谢您的帮助!


问题答案:

您可以通过多种方式执行此操作,建议您向服务器创建一个单独的请求类型,以接受文件名和文件位置(即文件在文件中连接失败的位置)。

这就是从客户端的服务器获取文件的方式:

int filePosition = 0;

InputStream is = clientSocket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();

do {
    baos.write(mybytearray);
    bytesRead = is.read(mybytearray);

    if(bytesRead != -1)
        filePosition += bytesRead;
}
while (bytesRead != -1);

现在,如果由于某种原因连接中断,您可以使用相同的文件名和 filePosition 再次向服务器发送请求,服务器将像下面这样发送文件:

OutputStream outToClient = socke.getOutputStream();
// The file name needs to come from the client which will be put in here below
File myfile = new File("D:\\ "+file_name);
byte[] mybytearray = new byte[(int) myfile.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myfile));
bis.skip(filePosition) //Advance the stream to the desired location in the file
bis.read(mybytearray, 0, mybytearray.length);
outToClient.write(mybytearray, 0, mybytearray.length);
System.out.println("Arrays on server:"+Arrays.toString(mybytearray));
outToClient.flush();
bis.close();

在客户端中,您可以打开文件流,并append = true在构造函数中指定如下所示:

FileOutputStream fos = new FileOutputStream("D:\\ "+file_name, true);

这可能是实现此目的的一种方法,还有很多选择。我还建议在传输后使用诸如MD5之类的哈希函数来验证文件,例如,它为给定的输入创建唯一的标记,并且对于相同的输入始终输出相同的结果,这意味着您可以从同一文件创建标记在服务器和客户端中,如果文件确实相同,它将生成相同的标记。由于图章的大小相对于它自己的文件来说很小,并且它也是固定的,因此可以在客户端/服务器之间发送它而没有太多开销。

您可以使用以下代码生成MD5哈希值:

MessageDigest md = MessageDigest.getInstance("MD5");
try (InputStream is = Files.newInputStream(Paths.get("file.txt"))) {
  DigestInputStream dis = new DigestInputStream(is, md);
  /* Read stream to EOF as normal... */
}
byte[] digest = md.digest();


 类似资料:
  • 问题内容: 检测插座是否已掉落的最合适方法是什么?还是实际上是否发送过数据包? 我有一个库,用于通过Apple网关(在GitHub上提供)将Apple Push Notifications发送到iPhone 。客户端需要打开一个套接字并发送每个消息的二进制表示形式。但不幸的是,Apple不会返回任何确认。该连接也可以重用于发送多个消息。我正在使用简单的Java套接字连接。相关代码为: 在某些情况下

  • 问题内容: 我正在使用OpenShift和WildFly 8.2.1 final来实现新的HTML5 websocket。我使用了本教程来设置这个项目。 每当我打开MyTest.html时,这就是JavaScript记录的内容: 服务器连接,然后立即断开连接。为什么?我究竟做错了什么?有什么我想念的吗? 这是模式代码-> serverendpoint.java MyTest.html: 和pom.

  • 在代理上使用HTTP隧道时,TCP套接字有问题。 客户端(C++)打开到服务器(JAVA)的TCP套接字。我添加了对HTTP代理的支持。一切正常,客户端发送“HTTP Connect”请求如下所示,并在以下情况下继续普通TCP连接: 然而,如果代理中配置了空闲超时,并且没有发送实际数据,则尽管客户端每60秒发送TCP保持活动数据包,但连接将终止。空闲超时配置为10分钟。

  • 我编写了简单的服务器/客户端程序,其中客户端将一些硬编码数据以小块形式发送给服务器程序,服务器程序正在等待数据,以便将其打印到终端。在客户端,我在循环中调用send(),同时有更多的数据要发送,而在服务器上,我使用read()执行同样的操作,即返回的字节数为 如果我在完成发送后专门在客户端的套接字上调用close(),那么这个示例非常有效,但如果我不这样做,服务器将不会实际退出read()循环,直

  • 问题内容: 大家好。我有一个使用ServerSocket和Socket类用Java编写的服务器。 我希望能够检测并处理断开连接,然后在必要时重新连接新客户端。 检测客户端断开连接,关闭套接字然后接受新客户端的正确步骤是什么? 问题答案: 大概是在从套接字读取数据,也许是在输入流上使用包装器,例如BufferedReader。在这种情况下,当相应的读取操作返回-1(对于原始read()调用)或为nu

  • 我的用例是周期性地轮询本地目录中的新文件列表,然后将它们上传到1个连接中的FTP服务器。Camel路由在Spring XML中定义如下: