Java: A client/server file transfer (incomplete files) - java

I am building an application that will send file across the network through sockets.
There are 2 programs. Server and Client each have two classes Download and Upload.
public class Download implements Runnable{
public ServerSocket server;
public Socket socket;
public int port;
public String saveTo = "";
public InputStream In;
public FileOutputStream Out;
public Download(String saveTo){
try {
server = new ServerSocket(1544);
port = 1544;
this.saveTo = saveTo;
}
catch (IOException ex) {
System.out.println("Exception [Download : Download(...)]");
}
}
#Override
public void run() {
try {
socket = server.accept();
In = socket.getInputStream();
Out = new FileOutputStream(saveTo);
byte[] buffer = new byte[1024];
int count;
while((count = In.read(buffer)) >= 0){
Out.write(buffer, 0, count);
}
Out.flush();
if(Out != null){ Out.close(); }
if(In != null){ In.close(); }
if(socket != null){ socket.close(); }
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
and class Upload:
public class Upload implements Runnable{
public String addr;
public int port;
public Socket socket;
public FileInputStream In;
public OutputStream Out;
public File file;
public Upload(String addr, int port, File filepath){
super();
try {
file = filepath;
socket = new Socket("127.0.0.1",1545);
Out = socket.getOutputStream();
In = new FileInputStream(filepath);
}
catch (Exception ex) {
System.out.println("Exception [Upload : Upload(...)]");
}
}
#Override
public void run() {
try {
byte[] buffer = new byte[1024];
int count;
while((count = In.read(buffer)) >= 0){
Out.write(buffer, 0, count);
}
Out.flush();
if(In != null){ In.close(); }
if(Out != null){ Out.close(); }
if(socket != null){ socket.close(); }
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
And in the class server:
File myFile = new File("temp");
Upload upl = new Upload("temp", 1544,myFile)
fileThreadSend = new Thread(upl);
fileThreadSend.start();
and in class client:
Download dwn = new Download("temp");
Thread fileThread = new Thread(dwn);
fileThread.start();
the problem runs but it doesn't transfer all the file
sometimes it transfer just 9kb of it and sometimes 20 MBS.
what is wrong?
I tried to search but couldn't find applicable any solution.
Thanks in advance

Don't be bothered and use what the JDK has to offer:
create a file from an InputStream;
send the contents of a file to an OutputStream.
More details here. And don't forget to use try-with-resources.
Also, avoid using Thread directly and use an ExecutorService instead.

Related

IndexOutOfBoundsException when transferring a file through sockets. urgent data transfer control

How can I resolve this error when transferring a file through sockets:
java.lang.IndexOutOfBoundsException
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at Client.getFile(Client.java:18)
I implemented a client server application for transferring a file using the TCP protocol. Server is parallel. It is also necessary to implement transmission control using urgent data. I did not find a solution on Java on the Internet.
Class Server:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private ServerSocket serverSocket;
public void start(int port) throws IOException {
serverSocket = new ServerSocket(port);
while (true)
new ClientHandler(serverSocket.accept()).start();
}
public void stop() throws IOException{
serverSocket.close();
}
private static class ClientHandler extends Thread {
private Socket clientSocket;
private DataOutputStream out;
private FileInputStream in;
public ClientHandler(Socket socket) {
this.clientSocket = socket;
}
public void run() {
try {
out = new DataOutputStream(clientSocket.getOutputStream());
out.writeInt((int) Prop.FILE_1.length());
} catch (IOException e) {
e.printStackTrace();
}
try {
in = new FileInputStream(Prop.FILE_1);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
byte buf[] = new byte[512];
int len = 0;
try {
len = in.read(buf);
} catch (IOException e) {
e.printStackTrace();
}
if(len == -1) {
break;
}
try {
out.write(buf, 0, len);
} catch (IOException e) {
e.printStackTrace();
}
try {
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
/*try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}*/
}
}
}
Class Client:
import java.io.*;
import java.net.Socket;
public class Client {
private Socket clientSocket;
private FileOutputStream out;
private DataInputStream in;
public String getFile() throws IOException {
int i = 0;
int len;
byte buf[] = new byte[512];
Integer fileSize;
fileSize = in.readInt();
while (i < fileSize) {
len = in.read(buf);
if (len == -1) {
break;
}
i += len;
out.write(buf, 0, len);
out.flush();
}
out.close();
return in.readUTF();
}
public void startConnection(String ip, int port) throws IOException {
clientSocket = new Socket(ip, port);
out = new FileOutputStream(Prop.FILE_2);
in = new DataInputStream(clientSocket.getInputStream());
}
public void stopConnection() throws IOException {
in.close();
out.close();
clientSocket.close();
}
}
Test
public class TestCS {
#Test
// (threadPoolSize = 3, invocationCount = 6, timeOut = 1000)
public void givenClient1__whenServerResponds__thenCorrect() throws IOException {
SoftAssert softAssert = new SoftAssert();
Client client1 = new Client();
client1.startConnection("127.0.0.1", 555);
String file = client1.getFile();
System.out.println(file);
client1.stopConnection();
softAssert.assertEquals(file, "First file!!!");
softAssert.assertAll();
}
}
You are reading InputStream wrongly. The logic you are trying to put there is already available in DataInputStream.read(..) method. All you have to do is to check how many bytes it read from the stream.
Change your while loop in Client like this
while (i < fileSize) {
// javadoc for below : - https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#read(byte[])
len = in.read(buf);
if(len<0) {
break;
}
i += len;
out.write(buf, 0, len);
out.flush();
}
Note : I have not checked your logic. All I checked and corrected is the Exception you got.
Also, typically we do not read fileSize upfront. You generally keep on reading stream till you get EOF (-1) from the stream. Please check that logic as well.

Send files with java socket

i am sending files from two java applications here the source code of the server and the client
public class FileClient {
private Socket s;
public FileClient(String host, int port, String file) {
try {
s = new Socket(host, port);
sendFile(file);
} catch (Exception e) {
e.printStackTrace();
}
}
public void sendFile(String file) throws IOException {
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[4096];
while ((fis.read(buffer) > 0)) {
dos.write(buffer);
}
fis.close();
dos.close();
}
public static void main(String[] args) {
FileClient fc = new FileClient("192.168.0.167", 1988, "C:/Users/mhattabi/Desktop/fileData.txt");
}
}
and here the source code of the server
public class FileServer extends Thread {
private ServerSocket ss;
public FileServer(int port) {
try {
ss = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
try {
Socket clientSock = ss.accept();
saveFile(clientSock);
// ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void saveFile(Socket clientSock) throws IOException {
DataInputStream dis = new DataInputStream(clientSock.getInputStream());
FileOutputStream fos = new FileOutputStream("fileData.txt");
byte[] buffer = new byte[4096];
int filesize = 15123; // Send file size in separate msg
int read = 0;
int totalRead = 0;
int remaining = filesize;
while((read = dis.read(buffer)) > 0) {
totalRead += read;
System.out.println("read " + totalRead + " bytes.");
fos.write(buffer, 0, read);
}
fos.close();
dis.close();
}
public static void main(String[] args) {
FileServer fs = new FileServer(1988);
fs.start();
}
}
the problem that in the server i received the file but there is extra character in it look like this.Any help will be appreciated thanks
Usual problem.
while ((fis.read(buffer) > 0)) {
dos.write(buffer);
}
You're ignoring the count returned by the read, and assuming that it filled the buffer. It should be:
while ((count = fis.read(buffer) > 0)) {
dos.write(buffer, 0, count);
}
Curiously enough you have this right in the server. NB You don't need a DataOutputStream here.
byte[] buffer = new byte[4096];
I think the" extra character" come from this place;every time you write 4096 byte
,at last time it happened less than 4096 byte.and then you get extra character

Multiple file chunks transfer over socket to multiple clients

I have to transfer chunks of a file to different clients using one server.
When i run the server file and provide the name of the file it successfully makes chunks. when i run the first client for first time it works but when i run it for the client again(by that i mean when i connect as a second client) it fails to transfer chunks to the second client. Complete code of server and client are shown below.
error is for the second client it starts reading the contents of the file as filename and program terminates.
provide a large text file(1MB) file as input to server
Server Code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
public class server {
private static final int sPort = 8000; //The server will be listening on this port number
public static String str;
public static int c;
public static void main(String[] args) throws Exception {
System.out.println("The server is running.");
ServerSocket listener = new ServerSocket(sPort);
int clientNum = 1;
System.out.println("Enter the name of the file: ");
Scanner in = new Scanner(System.in);
str = in.nextLine();
String path = System.getProperty("user.dir");
String filepath = path +"/"+ str;
in.close();
try {
c=splitFile(new File(filepath));
} catch (IOException e1) {
e1.printStackTrace();
}
try {
while(true) {
new Handler(listener.accept(),clientNum,c).start();
System.out.println("Client " + clientNum + " is connected!");
clientNum++;
}
} finally {
listener.close();
}
}
/**
* A handler thread class. Handlers are spawned from the listening
* loop and are responsible for dealing with a single client's requests.
*/
private static class Handler extends Thread {
private Socket connection;
private int chunkcount;
private ObjectInputStream in; //stream read from the socket
private ObjectOutputStream out; //stream write to the socket
private int no; //The index number of the client
public Handler(Socket connection, int no,int c) {
this.connection = connection;
this.no = no;
this.chunkcount=c;
}
public void run() {
try{
//initialize Input and Output streams
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
in = new ObjectInputStream(connection.getInputStream());
try{
String path = System.getProperty("user.dir");
path=path+"/"+"chunks"+ "/";
System.out.println(path);
System.out.println("Total chunks: "+chunkcount);
int i=no;
int j=i;
int k=0;
OutputStream op=connection.getOutputStream();
DataOutputStream d = new DataOutputStream(op);
d.writeInt(no);
d.flush();
System.out.println("value of j or clientnum: "+j);
while(j<chunkcount)
{
k++;
j=j+5;
}
System.out.println(k);
d.writeInt(k);
d.flush();
//d.close();
while(i<chunkcount)
{
String pathname= path+Integer.toString(i)+str;
System.out.println(i+str);
sendFile(connection,pathname);
i=i+5;
}
}
catch(Exception e){
e.printStackTrace();
}
}
catch(IOException ioException){
System.out.println("Disconnect with Client " + no);
}
finally{
//Close connections
try{
in.close();
out.close();
connection.close();
}
catch(IOException ioException){
System.out.println("Disconnect with Client " + no);
}
}
}
}
public static int splitFile(File f) throws IOException {
int partCounter = 1;//I like to name parts from 001, 002, 003, ...
//you can change it to 0 if you want 000, 001, ...
int sizeOfFiles = 102400;// 1MB
byte[] buffer = new byte[sizeOfFiles];
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(f))) {//try-with-resources to ensure closing stream
String name = f.getName();
String path = f.getParent();
long sizefile = f.getTotalSpace();
String newpath = path + "/" + "chunks";
File dir = new File(newpath);
dir.mkdir();
int tmp = 0;
while ((tmp = bis.read(buffer)) > 0) {
//write each chunk of data into separate file with different number in name
File newFile = new File(dir, String.format("%d", partCounter++) + name );
//System.out.println(f.getParent());
try (FileOutputStream out = new FileOutputStream(newFile)) {
out.write(buffer, 0, tmp);//tmp is chunk size
}
}
System.out.println("File details are : "+name+" "+sizefile);
System.out.println("Number of chunks: "+ (partCounter-1));
}
return (partCounter-1);
}
public static void sendFile(Socket conn,String fileName) throws IOException
{
File myFile = new File(fileName);
byte[] mybytearray = new byte[(int) myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
dis.readFully(mybytearray, 0, mybytearray.length);
OutputStream os = conn.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(myFile.getName());
dos.writeLong(mybytearray.length);
dos.write(mybytearray, 0, mybytearray.length);
dos.flush();
dis.close();
}
}
client code:
import java.net.*;
import java.io.*;
public class Client {
Socket requestSocket; //socket connect to the server
ObjectOutputStream out; //stream write to the socket
ObjectInputStream in; //stream read from the socket
public Client() {}
void run()
{
try{
//create a socket to connect to the server
requestSocket = new Socket("localhost", 8000);
System.out.println("Connected to localhost in port 8000");
//initialize inputStream and outputStream
out = new ObjectOutputStream(requestSocket.getOutputStream());
out.flush();
in = new ObjectInputStream(requestSocket.getInputStream());
System.out.println("Ready to receive files ( Enter QUIT to end):");
BufferedInputStream in1 = new BufferedInputStream(requestSocket.getInputStream());
DataInputStream d = new DataInputStream(in1);
int clientnum=d.readInt();
String path = System.getProperty("user.dir");
String oppath = path + "/" + "Client" + clientnum;
File dir = new File(oppath);
dir.mkdir();
int numchunk=d.readInt();
System.out.println(numchunk);
int jakarta=1;
while(jakarta<=numchunk ){
jakarta++;
String newpath=oppath+"/";
File f = new File(newpath);
f.createNewFile();
receiveFile(requestSocket,newpath);
System.out.println("File Received");
}
}
catch (ConnectException e) {
System.err.println("Connection refused. You need to initiate a server first.");
}
catch(UnknownHostException unknownHost){
System.err.println("You are trying to connect to an unknown host!");
}
catch(IOException ioException){
ioException.printStackTrace();
}
finally{
//Close connections
try{
in.close();
out.close();
requestSocket.close();
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
}
//send a message to the output stream
public static void receiveFile(Socket s1,String oppath) throws IOException
{
String fileName;
try {
int bytesRead;
InputStream in = s1.getInputStream();
DataInputStream clientData = new DataInputStream(in);
fileName = clientData.readUTF();
OutputStream output = new FileOutputStream(oppath+fileName);
long size = clientData.readLong();
byte[] buffer = new byte[1024];
while (size > 0
&& (bytesRead = clientData.read(buffer, 0,
(int) Math.min(buffer.length, size))) != -1) {
output.write(buffer, 0, bytesRead);
size -= bytesRead;
}
output.flush();
output.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
//main method
public static void main(String args[])
{
Client client = new Client();
client.run();
}
}

File transfer Server to client - java

I am trying to write the server client file transfer program in java.
Role of Server:-
a) Serve a file to a client (one).
b) Server will send file 1 byte at a time.
c) Should be able to send the file more than once.
Role of Client:-
a) Client downloads a file
b) Client should buffer the file before writing to disk( <= 100kb) I.e. buffer 100KB and write to disk then repeat this till 1MB
I wrote the code to transfer the file from Server to Client but there seem to have some issues with the program. Server starts sending the data but its lost in the transaction. Also the content of file to be transferred is erased. As I couldn't see any specific error on console so I couldn't figure out the bug. If anyone guide me whether this approach is correct or if not, please suggest proper changes.
*Server*
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
FileOutputStream fileOutputStream = null;
BufferedOutputStream bufferedOutputStream = null;
int sizeBuffer = 0;
try{
try {
serverSocket = new ServerSocket(55555);
} catch (IOException ex) {
System.out.println("Error: Unable to Connect to Server ");
}
System.out.println("Created Socket");
try {
socket = serverSocket.accept();
} catch (IOException ex) {
System.out.println("Error: Unable to connect to client ");
}
System.out.println("Accepted Client Connection ");
try {
inputStream = socket.getInputStream();
sizeBuffer = socket.getReceiveBufferSize();
System.out.println("Size of Buffer " + sizeBuffer);
} catch (IOException ex) {
System.out.println("Error: unable to ger socket input stream ");
}
try {
fileOutputStream = new FileOutputStream("D:/ServerFile.txt");
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
} catch (FileNotFoundException ex) {
System.out.println("File not found. ");
}
byte[] bytes = new byte[sizeBuffer];
int count;
while ((count = inputStream.read(bytes)) > 0) {
bufferedOutputStream.write(bytes, 0, count);
}
System.out.println("Done");
}// end of first try
finally{
bufferedOutputStream.flush();
bufferedOutputStream.close();
inputStream.close();
socket.close();
serverSocket.close();
}
}
}
And here is client side code !
*Client*
public class Client {
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = null;
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOuptputStream = null;
Socket socket = null;
int count;
try{
try {
socket = new Socket("127.0.0.1", 55555);
} catch (IOException ex) {
System.out.println("Error: Unable to create Socket ");
}
File file = new File("D:/ClientFile.txt");
long fileLength = file.length();
System.out.println(fileLength);
if ( Integer.MAX_VALUE < fileLength ) {
System.out.println("Error: Exceeded the size of transfer");
}
byte[] bytes = new byte[(int) fileLength];
try{
fileInputStream = new FileInputStream(file);
}catch (IOException ex){
System.out.println("Error: Unable to open fileInputStream");
}
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedOuptputStream = new BufferedOutputStream(socket.getOutputStream());
while ((count = bufferedInputStream.read(bytes)) > 0) {
bufferedOuptputStream.write(bytes, 0, count);
}
}
finally{
bufferedOuptputStream.flush();
bufferedOuptputStream.close();
fileInputStream.close();
bufferedInputStream.close();
socket.close();
}
}
}

Send a stop message in a socket

I want a efficient and a fast way of sending a stop message in a socket.
I have a method that send files from one pc to another. All of the files from the sender appear on the receiver's PC. However all of the data is being written to the first file (only). The other files exist, but are empty. This happen because the receiver method doesn't know when to start writing to the next file.
Sender
public static void sendFile (final Socket sock, File source)
{
FileInputStream fileIn = null;
try
{
//Read bytes from the source file
fileIn = new FileInputStream(source);
//Write bytes to the receive
//No need to use a buffered class, we make our own buffer.
OutputStream netOut = sock.getOutputStream();
byte[] buffer = new byte[BUFFER_SIZE];
int read;
while ((read = fileIn.read(buffer)) != -1)
{
netOut.write(buffer, 0, read);
netOut.flush ();
}
//Send some stop message here
}
catch (Exception e)
{
e.printStackTrace ();
}
finally
{
if (fileIn != null)
{
try
{
fileIn.close ();
}
catch (IOException e)
{
e.printStackTrace ();
}
}
}
}
//Send files via socket
public static void sendFile (final Socket sock, File[] source)
{
for (int i = 0; i < source.length; i++)
sendFile (sock, source[i]);
}
Receiver:
public static void receiveFile (final Socket sock, File destination)
{
BufferedOutputStream out = null;
try
{
//Receive data from socket
InputStream clientInputStream = sock.getInputStream();
//Write bytes to a file
out = new BufferedOutputStream (new FileOutputStream (destination));
byte[] buffer = new byte[BUFFER_SIZE];
int read;
while (true)
{
read = clientInputStream.read(buffer);
out.write(buffer, 0, read);
out.flush ();
}
}
catch (IOException e)
{
e.printStackTrace ();
}
finally
{
if (out != null)
{
try
{
out.close ();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
//Receive files via socket
public static void receiveFile (final Socket sock, File[] destination)
{
for (int i = 0; i < destination.length; i++)
receiveFile (sock, destination[i]);
}
You need to modify your send/receive protocol to include at least a minimal header before sending the file. Your header should include at least the size of the data to follow, and anything else you might want (such as file name).
I tried with a header like you suggested, but it doesn't work. The receiver still don't know when to stop(so I get EOFException). All the received data get written to the first file.
public static void sendFile (Socket sock, File source)
{
FileInputStream fileIn = null;
try
{
//Read bytes from the source file
fileIn = new FileInputStream(source);
//Write bytes to the receive
//No need to use a buffered class, we make our own buffer.
OutputStream netOut = sock.getOutputStream();
byte[] buffer = new byte[BUFFER_SIZE];
int readBytes = 0;
long fileSize = source.length();
long counter = 0;
//Send the file size
DataOutputStream objOut = new DataOutputStream (netOut);
System.out.println ("Writing: " + source.length ());
objOut.writeLong (fileSize);
objOut.flush ();
while ((counter += readBytes) < fileSize)
{
readBytes = fileIn.read(buffer);
netOut.write(buffer, 0, readBytes);
netOut.flush ();
}
fileIn.close();
}
catch (Exception e)
{
e.printStackTrace ();
}
finally
{
if (fileIn != null)
{
try
{
fileIn.close ();
}
catch (IOException e)
{
e.printStackTrace ();
}
}
}
}
[]
public static void receiveFile (Socket sock, File destination)
{
BufferedOutputStream fileOut = null;
try
{
//Receive data from socket
InputStream netIn = sock.getInputStream();
//Write bytes to a file
fileOut = new BufferedOutputStream (new FileOutputStream (destination));
byte[] buffer = new byte[BUFFER_SIZE];
int readBytes = 0;
long fileSize;
long counter = 0;
//Receive the file size
DataInputStream objIn = new DataInputStream (netIn);
fileSize = objIn.readLong ();
System.out.println ("Receiving: " + fileSize);
while (true)
{
readBytes = netIn.read (buffer);
fileOut.write (buffer, 0, readBytes);
fileOut.flush ();
counter += readBytes;
if (counter > fileSize)
break;
}
}
catch (IOException e)
{
e.printStackTrace ();
}
finally
{
if (fileOut != null)
{
try
{
fileOut.close ();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
System.out.println ("Ending method");
}

Categories