首页 > 解决方案 > 使用 java scoket 在接收到的文件中获取额外的字节

问题描述

我已经使用 java socket 实现了一个文件传输程序。在这个程序中,从客户端发送一个文件,然后将其下载到服务器中。该程序几乎可以正常工作,但问题是接收到的字节长度总是大于从客户端发送的字节长度。例如,我从客户端发送了 678888589 字节,但是当我在服务器检查接收到的文件的长度时,我得到了 678925260 字节。出于这个原因,我在服务器端得到了不同的校验和。

这是我的代码:客户端类:

public class Client  
{ 
    final static int ServerPort = 1234; 
    public static final int BUFFER_SIZE = 1024 * 50;
    private static byte[] buffer;

    public static void main(String args[]) throws UnknownHostException, IOException  
    { 
        Scanner scn = new Scanner(System.in);
        buffer = new byte[BUFFER_SIZE];

    for(int i=0;i<8;i++) {
        Socket s1 = new Socket(ip, ServerPort); 
        DataOutputStream dos1 = new DataOutputStream(s1.getOutputStream());
        SendMessage message = new SendMessage(s1, "test.mp4",dos1);
        Thread t = new Thread(message); 
        System.out.println("Adding this client to active client list"); 
        t.start();
    }
  }
}

class SendMessage implements Runnable{
    String file_name;
    Socket s;
    public final int BUFFER_SIZE = 1024 * 50;
    private byte[] buffer;
    DataOutputStream dos;

public SendMessage(Socket sc,String file_name,DataOutputStream dos) {
    this.file_name = file_name;
    this.s=sc;
    buffer = new byte[BUFFER_SIZE];
    this.dos = dos;
}

@Override
public void run() { 
    File file = new File(file_name);
    try {
        sendFile(file, dos);
        dos.close();
        while(true) {

        }
    } catch (IOException e1) {
        e1.printStackTrace();
    }

} 


public void sendFile(File file, DataOutputStream dos) throws IOException {
    byte[] buffer = new byte[BUFFER_SIZE+1];
    if(dos!=null&&file.exists()&&file.isFile())
    {
        FileInputStream input = new FileInputStream(file);
        dos.writeLong(file.length());

      System.out.println(file.getAbsolutePath());
        int read = 0;
        int totalLength = 0;
        while ((read = input.read(buffer)) != -1) {
            dos.write(buffer);
            totalLength +=read;
            System.out.println("length "+read);
        }
        input.close();
        System.out.println("File successfully sent! "+totalLength);
    }
}

}

服务器类

// Server class 
public class Server 
{ 

    // Vector to store active clients 
    static Vector<ClientHandler> ar = new Vector<>(); 

    // counter for clients 
    static int i = 0; 

    public static void main(String[] args) throws IOException 
    { 
        // server is listening on port 1234 
        ServerSocket ss = new ServerSocket(1234); 

        Socket s; 

        // running infinite loop for getting 
        // client request 
        while (true) 
        { 
            // Accept the incoming request 
            s = ss.accept(); 

            System.out.println("New client request received : " + s); 

            // obtain input and output streams 
            DataInputStream dis = new DataInputStream(s.getInputStream()); 
            DataOutputStream dos = new DataOutputStream(s.getOutputStream()); 

            System.out.println("Creating a new handler for this client..."); 

            // Create a new handler object for handling this request. 
            ClientHandler mtch = new ClientHandler(s,"client " + i, dis, dos); 

            // Create a new Thread with this object. 
            Thread t = new Thread(mtch); 

            System.out.println("Adding this client to active client list"); 

            // add this client to active clients list 
            ar.add(mtch); 

            // start the thread. 
            t.start(); 

            // increment i for new client. 
            // i is used for naming only, and can be replaced 
            // by any naming scheme 
            i++; 

        } 
    } 
} 

// ClientHandler class 
class ClientHandler implements Runnable 
{ 
    Scanner scn = new Scanner(System.in); 
    private String name; 
    final DataInputStream dis; 
    final DataOutputStream dos; 
    Socket s; 
    boolean isloggedin; 
    public static final int BUFFER_SIZE = 1024*50;
    private byte[] buffer;

    // constructor 
    public ClientHandler(Socket s, String name, 
            DataInputStream dis, DataOutputStream dos) { 
        this.dis = dis; 
        this.dos = dos; 
        this.name = name; 
        this.s = s; 
        this.isloggedin=true; 
        buffer = new byte[BUFFER_SIZE];
    } 

    @Override
    public void run() { 
        String received;
        BufferedOutputStream out = null;
        String outputFile = "out_"+this.name+".mp4";
        BufferedInputStream in = null;
        try {
            in = new BufferedInputStream(s.getInputStream());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            out = new BufferedOutputStream(new FileOutputStream(outputFile));
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
//      while (true) 
//      { 
            try
            { 


                long length = -1;
                length = dis.readLong();
                if(length!=-1)System.out.println("length "+length);

//              String checkSum = dis.readUTF();
//              System.out.println(checkSum);

                int len=0;
                long totalLength = 0;

//              int len = 0;
                while ((len = in.read(buffer,0,BUFFER_SIZE)) > 0) {
                    out.write(buffer, 0, len);
                    totalLength+=len;
//                  if(len<BUFFER_SIZE)break;
//                  System.out.println("length "+len);
                    if(len<=0)break;
                }

                File file = new File(outputFile);

                System.out.println("total length1 "+totalLength+ " dif "+(totalLength-length));

                System.out.println("output length "+file.length());         

            } catch (IOException e) { 

                e.printStackTrace(); 
            } 

    }

    private static String checksum(String filepath, MessageDigest md) throws IOException {

        // file hashing with DigestInputStream
        try (DigestInputStream dis = new DigestInputStream(new FileInputStream(filepath), md)) {
            while (dis.read() != -1) ; //empty loop to clear the data
            md = dis.getMessageDigest();
        }

        // bytes to hex
        StringBuilder result = new StringBuilder();
        for (byte b : md.digest()) {
            result.append(String.format("%02x", b));
        }
        return result.toString();

    }
}

如果有人能告诉我我做错了什么,那就太好了。另外,如何验证服务器端的校验和。另一个问题是服务器端代码在此块中被阻止。

while ((len = in.read(buffer,0,BUFFER_SIZE)) > 0) {
    out.write(buffer, 0, len);
    System.out.println("length "+len);
    if(len<=0)break;
}

除非客户端断开连接,否则它不能中断循环。尽管文件已正确接收。

问候。

标签: javamultithreading

解决方案


您在客户端代码上犯了一个小错误。您正在写出完整的缓冲区,而不是从文件中读取的内容。

        while ((read = input.read(buffer)) != -1) {
            dos.write(buffer,0,read);
            totalLength += read;
            System.out.println("length " + read);
        }

推荐阅读