Java TCP 文件传输应用程序

3

您好,感谢您抽出时间阅读。我正在尝试使用TCP开发一个简单的Java文件传输应用程序。到目前为止,使用我的客户端和服务器类,我已经成功添加了一个工作上传方法(将文件上传到运行服务器的计算机)。

我还没有太多经验,所以进展比较缓慢。我还需要添加下载选项(从服务器获取文件),列出服务器上的所有文件,并且还需要一个选项,允许我从服务器中删除任何文件。

对于服务器和客户端,我都使用了特定的默认文件夹(在这种情况下是C:/Sharedfolder)。目前我的问题是:

  1. 在我的当前服务器代码中,上传到服务器的文件被重命名为“newfile”。如何使它更改文件名为类似于“oldfile_new”的内容(其中oldfile是实际原始文件的名称)?
  2. 使用我下面的当前服务器代码,我可以创建一个客户端类来从服务器下载文件吗?我该如何做?上传部分对我来说很有意义,但我仍在努力弄清楚如何从服务器下载/列出文件。
  3. 我目前正在使用预定义的主机IP,但最终我需要修改应用程序,以便客户端发送UDP广播以在私有网络上查找服务器。有人能指点我如何做吗?

我的当前服务器代码如下:

public class Server {

public static void main(String[] args) throws IOException {

    ServerSocket serverSocket = null;

    try {
        serverSocket = new ServerSocket(4555);
    } catch (IOException ex) {
        System.out.println("Can't setup server on this port number.\n");
    }

    Socket socket = null;
    InputStream is = null;
    OutputStream fos = null;
    BufferedOutputStream bos = null;
    int bufferSize = 0;
    System.out.println("Ready...");

    try {
        socket = serverSocket.accept();
    } catch (IOException ex) {
        System.out.println("Can't accept client connection.\n");
    }

    try {
        is = socket.getInputStream();

        bufferSize = socket.getReceiveBufferSize();
        System.out.println("Buffer size: " + bufferSize);
    } catch (IOException ex) {
        System.out.println("Can't get socket input stream.\n");
    }

    try {
        fos = new FileOutputStream("C:\\Sharedfolder\\newfile");
        bos = new BufferedOutputStream(fos);

    } catch (FileNotFoundException ex) {
        System.out.println("File not found.\n");
    }

    byte[] bytes = new byte[bufferSize];

    int count;

    while ((count = is.read(bytes)) > 0) {
        bos.write(bytes, 0, count);
    }

    bos.flush();
    bos.close();
    is.close();
    socket.close();
    serverSocket.close();

}

任何帮助都将不胜感激。谢谢 :)

客户端和服务器之间唯一的区别是谁创建了连接,之后你会得到一个套接字,在两端看起来都是相同的。我建议你提取发送文件的代码和另一个接收文件的方法。不同之处在于服务器将发送而不是客户端,客户端将接收而不是发送。进程在后台运行这个事实不应该有任何影响。客户端也可以在后台运行。 - Peter Lawrey
是的,我的问题在于(如果这太明显了,我很抱歉,因为我仍在努力理解)如何让服务器知道我想通过客户端从它那里获取文件。发送请求后,服务器如何知道我正在请求它的文件?因为至少对我来说,当前的代码似乎只允许服务器接收文件。 - Jaqualembo
这是有意义的。我该如何发送一个命令?通过 [is = socket.getInputStream()] 的输出吗?我会试着用这个做些尝试,谢谢。 - Jaqualembo
2
这是一个编程练习吗?那么ssh/scp、sftp、rsync等呢?所有这些协议都有Java客户端和服务器的实现。除非没有任何经过充分测试的免费实现适用于你,否则没有重新发明轮子的必要。 - Jim Garrison
当你遇到异常时,请打印或记录该异常。不要替换为自己设计的任意消息,这会使正确的调试变得不可能。 - user207421
显示剩余3条评论
2个回答

1

我曾经使用Java构建了一个使用加密和证书的客户端-服务器安全文件传输通道,也许我可以给你一些帮助。

问题1:要从客户端获取文件名,您必须在传输文件数据之前将文件名传输到服务器。

问题2:要从服务器下载文件,您需要向服务器发送一个信号(文件下载/上传请求),告诉它是下载还是上传操作,看起来非常像FTP协议。这样的信号应预先传输到服务器端。因此,您必须打开与服务器端相同的套接字,并使用该套接字从服务器获取文件的inputStream。

public static boolean send(FileInputStream fis,OutputStream os) throws IOException, InterruptedException
{
    Thread.currentThread().sleep(1000);
     while(true)
        {
            int read=0;
        if(fis!=null)
            read=fis.read(buf);
        byte[] result=new byte[read];
        //System.out.println(read);
        // os.write(buf,0,read);

         System.arraycopy(buf, 0, result,0, read);
            os.write(result);
            if(read < BUFFER_SIZE)
            {
                //System.out.println("服务器向客户端发送read="+read);
            break;
            }
        }//while
    fis.close();    
    return true;
}

在该函数中,fis是将要发送的文件流,os是从套接字获取的输出流,如下所示:

s = new ServerSocket(6868);
socket= s.accept();
os=socket.getOutputStream();
问题3:您应该将IP地址、端口号和协议类型(TCP/UDP)作为主函数的参数进行设置。因此,您只需设置参数而不修改源代码,就可以使您的应用程序按照您想要的不同方向运行。
那就是我知道的。希望这能给您一些帮助。

1

有许多工具已经可以做到这一点,但这是一个很好的学习练习。

通常你不仅需要传输数据,还需要一些关于文件本身的信息:

  1. 从服务器向客户端发送文件名
  2. 从服务器向客户端发送文件大小
  3. 将文件数据发送到客户端。客户端可以使用步骤中接收到的大小来计算进度
  4. 从服务器向客户端发送文件的修改时间。客户端使用接收到的修改时间戳记文件

所有这些东西都可以通过你已经实例化的流对象发送,你只需要确保客户端/服务器之间的事件顺序正确即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接