【问题标题】:java: Transfer a file to the server and get the file from the server in upper casejava:将文件传输到服务器并从服务器获取大写文件
【发布时间】:2018-05-22 20:19:57
【问题描述】:

我想将一个 .txt 文件从客户端发送到服务器并以大写形式取回。 但是这段代码什么都不做。谁能告诉这里出了什么问题..?

服务器:从客户端获取文件并将其以大写形式发送回客户端。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;

public class Assignment4_Server {

    public static void main(String[] args) throws IOException {
        byte[] bytearray = new byte[4096];
        try (ServerSocket ss = new ServerSocket(4444)) {
            Socket s = ss.accept();
            InputStream is = s.getInputStream();
            OutputStream os = s.getOutputStream();
            int count;
            String data = null ;
            while((count = is.read(bytearray))>0){
                data = Arrays.toString(bytearray).toUpperCase();
                byte[] bytearrayout = data.getBytes();
                os.write(bytearrayout);
            }
            s.close();
        }
    }
}

CLIENT : 发送text.txt文件到服务器,转换成大写后取回文件。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;


public class Assignment4_client {
    public static void main(String[] args) throws IOException {
        File file = new File("test.txt");
        byte[] bytearray = new byte[4096];
        Socket sc = new Socket("localhost",4444);
        //send file
        int countS , countR;
        FileInputStream fis = new FileInputStream(file);
        BufferedInputStream bis = new BufferedInputStream(fis);
        OutputStream os = sc.getOutputStream();
        while((countS = bis.read(bytearray))>0){
        os.write(bytearray);
        }
        //recieve file in uppercase from server
        InputStream is = sc.getInputStream();
        byte[] bytearray2 = new byte[4096];
        FileOutputStream fos = new FileOutputStream(file);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        while((countR = is.read(bytearray2))>0){
            bos.write(bytearray2);
        }
    }   
}

【问题讨论】:

  • 你能比“但是这段代码什么都不做”更具体吗?你能调试吗?服务器是否似乎正在获取和处理文件,但处理并没有改变任何东西。
  • 您弄乱了指令,有些指令的顺序不正确。这些显然会引发异常,尤其是在客户端的 while 循环中。您的部分答案在这里:link。请记住,OutputStream 的 flush 方法什么都不做(link),最好使用适合您硬件的缓冲区大小,而不是试图一目了然地读取整个文件(使用 4096 -> 内存页面大小)。
  • @AlexC。按照您的建议进行更改后,代码现在可以正常工作,但它将[116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 116, 101, 115, 116, 32, 102, 105, 108, 101, 46, 0, 0, 0, 0,...] 写入文件中,而不是THIS IS A TEST FILE.

标签: java sockets file-transfer


【解决方案1】:

这是一个可以帮助您的代码。但在阅读之前,您应该了解正在发生的事情:

  1. 您的客户端没有向服务器发送“停止阅读”信息(阅读下面的客户端代码)。这就是为什么服务器在尝试读取客户端发送的数据时卡在 while 循环中的原因。这可能就是您尝试将数据直接发送回客户端的原因。关闭客户端的套接字输出以遵守 Socket 协定并正确释放套接字(请参阅 TCP/IP)。
  2. 给出的解决方案没有考虑到服务器在完成任务后应该保持运行。然后,服务器一次将不能为多个客户端提供服务。该服务器提供一次性服务,这是毫无意义的。为了克服这个问题,你应该把所有东西都放在一个while循环中,并将每个新的服务器进程绑定到一个新线程中(我让你这样做,这很有趣)。
  3. 服务器没有考虑数据的整体大小,如果数据太重,它可能会遇到内存不足的错误。您应该找到一种在实际实现中避免此问题的方法。
  4. 两个程序都应该捕获异常并将其记录在某处,以便您可以了解任何错误。
  5. 编写服务器并不是那么简单。您通常应该编写某种带有标头和其他类似内容的协议。为避免这种情况,请使用 ObjectOutputStream 和 ObjectInputStream 之类的对象,但它有一些限制,例如将您的服务器限制在 Java 世界中。

客户

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.Socket;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

public class Client {


    public void send(File file)
    {
        Socket sc = null;
        try
        {
            byte[] bytearray = new byte[4096];
            sc = new Socket("localhost", 4444);

            // 1. Read the file, send its content, close it. 
            int count;
            FileInputStream fis = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(fis);
            OutputStream os = sc.getOutputStream();

            while((count = bis.read(bytearray))>0)
            {
                os.write(bytearray);
            }
            fis.close();
            sc.shutdownOutput();

            // 2. Delete old file, receive data, write it to new File.
            InputStream is = sc.getInputStream();
            bytearray = new byte[4096];
            // Eventually do what you want with the file: new one, append, etc.
            file.delete();
            file.createNewFile();
            FileOutputStream fos = new FileOutputStream(file);
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
            count = 0;
            while((count = is.read(bytearray)) > 0)
            {
                bos.write(bytearray, 0, count);
            }
            fos.close();
            bos.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (sc != null)
            {
                try
                {
                    sc.close();
                } catch (IOException e) {}
            }
        }
    }
}

服务器

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server
{
    Server()
    {
        Socket s = null;
        byte[] bytearray = new byte[4096];
        try (ServerSocket ss = new ServerSocket(4444))
        {
            s = ss.accept();
            InputStream is = s.getInputStream();

            // 1. Recieve data and put it to UpperCase.
            String data = "";
            int count;
            while((count = is.read(bytearray)) > 0)
            {
                data += new String(bytearray, 0, count);
            }
            data = data.toUpperCase();
            System.out.println(data);

            // 2. Send back data.
            OutputStream os = s.getOutputStream();
            os.write(data.getBytes());
            os.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

测试程序

这个应该可以帮助您在 IDE 的同一个项目中测试您的两个程序。

import java.io.File;

public class Test
{
    public static void main(String[] args)
    {
        Client c = new Client();
        (new Thread()
        {
            public void run()
            {
                Server s = new Server();
            }
        }).start();
        c.send(new File("test.txt"));
    }
}

【讨论】:

  • 你没有测试过这段代码。这里offset的用法不正确;您忽略了发送代码中的读取计数;服务器不需要将整个请求读入内存; bytearray 未使用;并且这里的delete()createNewFile() 调用都是多余和浪费的。
  • 这段代码经过测试并适用于最初的问题。你怎么能说服务器不需要读取整个请求呢?你见过这样的服务器吗?至少你需要实现一个特定的协议来做到这一点,这绝对不是这里的情况。请阅读完整答案。
  • 如果此代码没有包含有关offset 变量的重大错误,您为什么要删除其中一个?而不是另一个?
【解决方案2】:

这里有两个简单的问题。

  1. 服务器在必须用于回复的套接字上读取直到流结束。因此客户端在发送提供EOS的请求后无法关闭它,因此它必须在发送请求后关闭套接字以进行输出。

  2. 您的复制循环是错误的。一般形式为:

    while ((count = in.read(buffer)) > 0)
    {
         out.write(buffer, 0, count);
    }
    

    您在写入时忽略了读取计数,因此您将在流结束时写入垃圾,或者read() 未填充buffer 的任何其他时间,可以是任何时间。

【讨论】:

  • 您只提供第一个答案。只是重新编辑。
  • @AlexC。不要在这里废话。我提供了一个正确的答案,它已经没有错误一些,但不是全部,你已经随后从你的答案中删除了。
猜你喜欢
  • 2011-02-04
  • 1970-01-01
  • 2015-11-21
  • 2012-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多