As said in the comments there are different issues in you code.
To recognise the end of single file you can simply add the file size after the filename separated by a Semicolon;
out.println(f.getName().split("\\.")[0] + "; size" + f.length());
On the Server side you accumulate the file size read / written stop read ing the content of the file close it and read the next line (filename / file size).
As said in the comments there are different issues.
You use fIn
and fOut
which is not clear how they are defined.
On the client side you use fOut
while the Socket OutputStream is named 'out'.
Similar thing on the server side. You read the number of files from in
but afterwards you get the InputStream (again?) from the Socket and use that as fIn
. Depending on your in
that may or may not work.
Also reading a line from via readLine
from an InputStream
and also binary content is not that trivial. In my example code I'm using the DataInputStream
for that even the readLine
method is deprecated.
The Example also uses the "try with resources" Syntax to ensure that all resources (Streams, Sockets) get closed in the case of an Exception.
The Example does not show how to deal with the file size on the server side That's up to you.
The example is completely runnable on a single machine and shows how to copy a single file via socket based on your code.
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class ClientServerSocketExample {
private static class Server {
public void run() throws IOException {
try (ServerSocket serverSocket = new ServerSocket(41000, 10, InetAddress.getLocalHost())) {
try (Socket client = serverSocket.accept()) {
try (DataInputStream in = new DataInputStream(client.getInputStream())) {
int g = Integer.parseInt(in.readLine());
if(g > -1) {
for(int i = 0; i < g; i++) {
String[] filenameAndSize = in.readLine().split(";");
String name = filenameAndSize[0];
byte[] bytes = new byte[16*1024];
File f = new File("/tmp/" + name + ".jar");
if(!f.exists()) f.createNewFile();
try (FileOutputStream fOut = new FileOutputStream(f)) {
int count;
while ((count = in.read(bytes)) >= 0) {
fOut.write(bytes, 0, count);
}
fOut.flush();
}
}
System.out.println("[" + client.getRemoteSocketAddress().toString() + "] added " + g + " new plugins.");
}
}
}
}
}
}
private static class Client {
public void run() throws IOException {
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(InetAddress.getLocalHost(), 41000) );
sendFiles(socket);
}
}
private static void sendFiles(Socket sock) throws IOException {
File[] files = new File[]{new File("some.jar")};
OutputStream fOut = sock.getOutputStream();
PrintStream out = new PrintStream(fOut);
out.println(files.length);
for(File f : files) {
out.println(f.getName().split("\\.")[0] + "; size" + f.length());
byte[] bytes = new byte[16 * 1024];
try (FileInputStream fIn = new FileInputStream(f)) {
int count;
while ((count = fIn.read(bytes)) >= 0) {
out.write(bytes, 0, count);
}
out.flush();
}
}
}
}
public static void main(String ... args) throws IOException, InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
try {
new Server().run();
} catch (IOException ioe) {
System.out.println(ioe);
}
}
}).start();
System.out.println("Waiting for the Server to come up");
Thread.sleep(500);
new Client().run();
}
}
There may be an issue in this solution when the client sends a \r
as new line separator and the file starts with \n
. The server may count the \n
as part of the line separator and the file will be corrupt (one byte will be missing).