首页 > 解决方案 > java客户端-服务器通信中的问题

问题描述

我已经在 java 中实现了客户端-服务器通信。以下是传输一组文件的代码:

服务器代码:

public class TransferServer {
static List<String> filesListInDir = new ArrayList<String>();
static String zipName = "tmp.tar.gz";
public static void main(String[] args) throws IOException, InterruptedException {
    // TODO Auto-generated method stub
    ServerSocket s1 = new ServerSocket(7104);
    System.out.println("Transfer server started");
    while (true) {
        Socket sckt = s1.accept();
        System.out.println("Request received. Please wait..");
        zipData();
        transferData(sckt);
        System.out.println("Data transferred");
    }
}
private static void transferData(Socket ts) throws IOException {
    FileInputStream fi=new FileInputStream(zipName);
    byte b[] = new byte[8000];
    fi.read(b, 0, b.length);
    OutputStream os = ts.getOutputStream();
    os.write(b, 0, b.length);
    fi.close();
}

客户端代码:

public class Fetchmyfile {
static String addr_list="/home/pi/addresslist.txt";
static String zipName = "tmp.tar.gz";
public static void main(String[] args) throws InterruptedException, IOException {
    // TODO Auto-generated method stub
        trigger();
}
private static void trigger() throws InterruptedException, IOException {
    // TODO Auto-generated method stub
    String[] hostList = readAddressList(addr_list);
    
    //remove tmp.zip
    for (int i = 0; i < hostList.length; i++) {
            Runtime r = Runtime.getRuntime();
            Process p = null;
            try {
                p = r.exec("rm /home/pi/combined_data/"+hostList[i]+"/"+zipName);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            p.waitFor();
    }
            
            //remove complete

    
    for (int i = 0; i < hostList.length; i++) {
        String addr = hostList[i];
        TransferClient clientInstance = new TransferClient();
        clientInstance.fileCopy(addr, "/home/pi/combined_data/"+addr.trim()+"/tmp.tar.gz");
    }
    System.out.println("All data has been transferred");
    
}

private static String[] readAddressList(String addr_list) throws IOException {
    FileReader fileReader = new FileReader(addr_list);
    
    BufferedReader bufferedReader = new BufferedReader(fileReader);
    List<String> lines = new ArrayList<String>();
    String line = null;
     
    while ((line = bufferedReader.readLine()) != null) 
    {
        lines.add(line);
    }
     
    bufferedReader.close();
    
    System.out.println("Loaded the host list");
    return lines.toArray(new String[lines.size()]);
    
}

}

public class TransferClient {


public boolean fileCopy(String sensor_node_ip, String filename) throws InterruptedException{
//public static void main(String args[]) throws IOException
    {
        try {
        //String filename = "‎�‎�localfile.zip";
        byte b[] = new byte[8000];
        Socket s = null;
        try {
            s = new Socket(sensor_node_ip, 7104);
            System.out.println("connection done");
        } catch (IOException e) {
            System.out.println("Couldn't connect to the server");
            return false;
        }
        InputStream iss = s.getInputStream();
        FileOutputStream fr = new FileOutputStream(filename);
        iss.read(b, 0, b.length);
        fr.write(b, 0, b.length);
        fr.close();
        s.close();
        //unZip(filename);
        System.out.println("Tar file recieved from " + sensor_node_ip);
        return true;
    }
        catch (IOException e){
            return false;
        }
    }
}

我面临的问题是,对于一个相对较大的文件,客户端创建一个具有预期名称的声明缓冲区大小的文件。但是该文件不可读并且是存档文件,无法提取。然而,服务器实际上拥有无论如何都是正确的文件。这可能是什么原因。任何建议/指针都非常感谢。

标签: javaclient-serverserversocket

解决方案


如我所见,问题是您正在写入 8000 字节,而不管输出的实际大小。您甚至没有尝试检查文件的大小,因此如果文件小于 8000 字节,您可能会写入垃圾,或者如果文件超过 8000 字节,则可能会截断它。

相反,您应该读取文件直到没有更多字节要读取,并确保您只写入实际读取的字节数(因为读取的字节数可能小于缓冲区长度)。

这确实是基本的 I/O。

因此,下面的示例将概念剥离为基本概念,仅关注客户端和服务器之间的文件传输。为了比较,我在每一端都添加了一个 MD5 检查,所以比较文件结果很容易。

编程的一个重要方面是,永远不要假设任何事情。始终查看您获得的内容并在运行时做出决定(例外情况是,如果它已预先记录并达成一致,但即便如此,我也会仔细检查,因为我不信任任何人)

服务器

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;

public class Server {
    public static void main(String[] args) {
        try (ServerSocket server = new ServerSocket(7104)) {
            Socket socket = server.accept();
            read(socket);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    protected static void read(Socket socket) {
        File target = new File("Target.file");
        try (InputStream is = socket.getInputStream(); OutputStream os = new FileOutputStream(target)) {
            byte bytes[] = new byte[1024];
            int bytesRead = -1;
            while ((bytesRead = is.read(bytes)) != -1) {
                os.write(bytes, 0, bytesRead);
            }
            System.out.println("Server MD5 = " + Util.getMD5Checksum(target));
        } catch (IOException | NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
    }

}

客户

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;

public class Client {

    public static void main(String[] args) {
        try {
            File source = new File(<BYO own file>);
            System.out.println("Client MD5 = " + Util.getMD5Checksum(source));
            try (Socket socket = new Socket("127.0.0.1", 7104); OutputStream os = socket.getOutputStream(); FileInputStream fis = new FileInputStream(source)) {
                byte bytes[] = new byte[1024];
                int bytesRead = -1;
                while ((bytesRead = fis.read(bytes)) != -1) {
                    os.write(bytes, 0, bytesRead);
                }
            } catch (IOException exp) {

            }
        } catch (IOException | NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
    }
}

MD5

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Util {

    protected static byte[] createChecksum(File filename) throws IOException, NoSuchAlgorithmException {
        try (InputStream fis = new FileInputStream(filename)) {

            byte[] buffer = new byte[1024];
            MessageDigest complete = MessageDigest.getInstance("MD5");
            int numRead;

            do {
                numRead = fis.read(buffer);
                if (numRead > 0) {
                    complete.update(buffer, 0, numRead);
                }
            } while (numRead != -1);

            return complete.digest();
        }
    }

    // see this How-to for a faster way to convert
    // a byte array to a HEX string
    public static String getMD5Checksum(File filename) throws IOException, NoSuchAlgorithmException {
        byte[] b = createChecksum(filename);
        String result = "";

        for (int i = 0; i < b.length; i++) {
            result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
        }
        return result;
    }
}

我强烈建议您花时间阅读Basic I/O,这些是您将一直重复使用的概念。


推荐阅读