Java 通过套接字传输多个文件问题

Java 通过套接字传输多个文件问题,java,Java,服务器端: public class Server { public static final String ALGORITHM = "RSA"; public static final String PRIVATE_KEY_FILE = "C:/Users/mrarsenal10/Desktop/server/key/private.key"; public static final String PUBLIC_KEY_FILE = "C:/Users/mrarsenal10/Desktop

服务器端:

public class Server 
{
public static final String ALGORITHM = "RSA";
public static final String PRIVATE_KEY_FILE = "C:/Users/mrarsenal10/Desktop/server/key/private.key";
public static final String PUBLIC_KEY_FILE = "C:/Users/mrarsenal10/Desktop/server/key/public.key";
public static void generateKey() 
{
    try 
    {
        final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
        keyGen.initialize(1024);
        final KeyPair key = keyGen.generateKeyPair();

        File privateKeyFile = new File(PRIVATE_KEY_FILE);
        File publicKeyFile = new File(PUBLIC_KEY_FILE);

    // Create files to store public and private key
        if (privateKeyFile.getParentFile() != null) {
            privateKeyFile.getParentFile().mkdirs();
        }
        privateKeyFile.createNewFile();

        if (publicKeyFile.getParentFile() != null) {
           publicKeyFile.getParentFile().mkdirs();
        }
        publicKeyFile.createNewFile();

        // Saving the Public key in a file
        ObjectOutputStream publicKeyOS = new ObjectOutputStream(
        new FileOutputStream(publicKeyFile));
        publicKeyOS.writeObject(key.getPublic());
        publicKeyOS.close();

        // Saving the Private key in a file
        ObjectOutputStream privateKeyOS = new ObjectOutputStream(
        new FileOutputStream(privateKeyFile));
        privateKeyOS.writeObject(key.getPrivate());
        privateKeyOS.close();
    }catch (Exception e) 
    {
        e.printStackTrace();
    }
}
public static boolean areKeysPresent() 
{
    File privateKey = new File(PRIVATE_KEY_FILE);
    File publicKey = new File(PUBLIC_KEY_FILE);

    if (privateKey.exists() && publicKey.exists())
    {
      return true;
    }
    return false;
}
public static String decrypt(byte[] text, PrivateKey key) { // giải mã
    byte[] dectyptedText = null;
    try {
    // get an RSA cipher object and print the provider
    final Cipher cipher = Cipher.getInstance(ALGORITHM);

    // decrypt the text using the private key
    cipher.init(Cipher.DECRYPT_MODE, key);
    dectyptedText = cipher.doFinal(text);

    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return new String(dectyptedText);
}
static void sendFile(Socket sock, String fName) throws FileNotFoundException, IOException
{
    File transferFile = new File (fName);
    byte [] bytearray = new byte [(int)transferFile.length()]; 
    FileInputStream fin = new FileInputStream(transferFile); 
    BufferedInputStream bin = new BufferedInputStream(fin); 
    bin.read(bytearray,0,bytearray.length); // luu  vao bytearray
    OutputStream os = sock.getOutputStream(); // goi outputstream de
    System.out.println("Sending Files..."); 
    os.write(bytearray,0,bytearray.length); 
    os.flush();
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
    if (!areKeysPresent()) {
        generateKey();
    }
    ServerSocket serverSocket = new ServerSocket(15124); 
    Socket sock = serverSocket.accept();   
    sendFile(sock, PUBLIC_KEY_FILE);
    sendFile(sock, "lich.txt");
    sock.close();
}
}
客户端:

public class Client
{
public static final String ALGORITHM = "RSA";
public static final String PUBLIC_KEY_FILE = "C:/Users/mrarsenal10/Desktop/Client/public.key";
static void recvFile(Socket sock, String fName) throws FileNotFoundException, IOException
{
    int filesize=1022386; 
    int bytesRead;
    int currentTot = 0;
    byte [] bytearray = new byte [filesize];
    InputStream is = sock.getInputStream(); 
    FileOutputStream fos = new FileOutputStream(fName); 
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    bytesRead = is.read(bytearray,0,bytearray.length); 
    currentTot = bytesRead; 
    do {
        bytesRead = is.read(bytearray, currentTot, (bytearray.length-currentTot));
        if(bytesRead >= 0) currentTot += bytesRead; } 
    while(bytesRead > -1);
    bos.write(bytearray, 0 , currentTot);
    bos.flush(); 
    bos.close();  
}
public static byte[] encrypt(String text, PublicKey key) {
    byte[] cipherText = null;
    try {
    // get an RSA cipher object and print the provider
    final Cipher cipher = Cipher.getInstance(ALGORITHM);
    // encrypt the plain text using the public key
    cipher.init(Cipher.ENCRYPT_MODE, key);
    cipherText = cipher.doFinal(text.getBytes());
    } catch (Exception e) {
        e.printStackTrace();
    }
    return cipherText;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
    Socket sock = new Socket("127.0.0.1",15124);
    recvFile(sock, "public.key");
    recvFile(sock, "lich.txt");
    sock.close();
}
}

我的问题是在这里我只能发送“public.key”或“lich.txt”从服务器到客户端,现在我想同时发送“public.key”和“lich.txt”。感谢您的帮助。

问题在于服务器和客户端的总体设计。在服务器端,它发送两个不同的文件,但在客户端,它只是一个数据流。一个字节表示一个文件中的数据与下一个文件中的数据没有区别。因此,您可能正在调用recvFile,它从服务器发送的两个文件接收所有数据。发送数据后,服务器关闭连接。(您可以显式地执行此操作。)因此,在客户端,您有一个无效的套接字。但是,您尝试使用表示第二个文件的套接字思想再次调用recvFile。这将导致您看到的SocketException或更可能的OutOfBoundsException

要解决这个问题,您需要在服务器和客户端之间添加更多的握手。最简单的是表示文件结尾的分隔符。更好的方法是在发送任何数据之前,在每个“消息”(也称为文件)的前面附加一个已知大小的头,让客户机知道文件的大小。然后,一旦客户端接收到报头,它就确切地知道要读取多少字节

现在,为了防止崩溃,您将
recvFile
方法更改为如下内容:

byte[] bytearray = new byte[4096];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream(fName);

int bytesRead;
while ((bytesRead = is.read(bytearray)) >= 0) {
    if (bytesRead > 0) {
        fos.write(bytearray, 0, bytesRead);
    }
}

fos.flush();
fos.close();

我已经对你的问题做了一些小的编辑,但是你应该强烈地考虑改写这个问题,并对它进行重新格式化,使我们更容易理解。