sending file over socket only works one time - java

I made a code that sending files from one computer to another,
the problem is that after one sending its not working anymore.
I know that the problem is when i'm writing to the writer but I don't know why its not working.
client:
File file =new File(path);
long fileSize = file.length();
long completed = 0;
int step = 150000;
Request req = new Request(RequetType.DOWNLOAD_FILE,file.getName());
writer.writeObject(req);
writer.flush();
// creates the file stream
FileInputStream fileStream = new FileInputStream(file);
// sending a message before streaming the file
// writer.writeObject("SENDING_FILE|" + file.getName() +"|" + fileSize);
writer.reset();
byte[] buffer = new byte[step];
while (completed <= fileSize) {
fileStream.read(buffer);
writer.write(buffer);
completed += step;
}
System.out.println(completed);
//writer.writeObject("SEND_COMPLETE");
fileStream.close();
server:
String filename = (String)req.getContent();
try {
FileOutputStream outStream =new FileOutputStream(Startdir+""+filename);
byte[] buffer = new byte[200000];
int bytesRead = 0, counter = 0;
bytesRead = this.reader.read(buffer);
if (bytesRead >= 0) {
outStream.write(buffer, 0, bytesRead);
counter += bytesRead;
System.out.println("total bytes read: " +
counter);
}
if (bytesRead < 1024) {
outStream.flush();
}
while (true)
{
bytesRead = this.reader.read(buffer);
if (bytesRead >= 0) {
outStream.write(buffer, 0, bytesRead);
counter += bytesRead;
System.out.println("total bytes read: " +
counter);
}
if (bytesRead ==0)
{
outStream.flush();
break;
}
}
System.out.println("Sent:"+filename+" from:"+MainApp.computersconnection.getIp());
} catch (Exception e) {
System.out.println("Error on downloading file!");
}

You need to flush the streams in the end even if the file isn't 0 bytes long. Try implementing that change and tell me if it still gives you trouble.
(Flush the output stream when your done sending a file).

Related

Pdf File does not display text correctly when sent over socket connection

I'm sending a pdf file from my java server to an android client. However when I look at the pdf file on the phone, the text is sometimes wrong (just some random symbols). Does someone know what is causing that problem?
Here is the code of the server:
private void sendPdfToPhone(File pdf) {
try {
InputStream iS = new FileInputStream(pdf);
DataOutputStream dOS = new DataOutputStream(new BufferedOutputStream(this.clientSocket.getOutputStream()));
String filename = pdf.getName();
byte[] bytes = new byte[(int) pdf.length()];
dOS.writeUTF(filename);
dOS.writeLong(bytes.length);
byte[] buffer = new byte[8192];
int bytesRead;
int bytesSent = 0;
while ((bytesRead = iS.read(buffer)) > 0) {
dOS.write(buffer, 0, bytesRead);
bytesSent += bytesRead;
}
dOS.close();
logger.debug("Sent file " + filename + " to Client: " + bytesSent + " / " + bytes.length);
} catch (IOException ex) {
logger.fatal(ex);
}
}
And this is the code of the Android client:
int bytesRead;
String filename = dIS.readUTF();
long fileSize = dIS.readLong();
byte[] buffer = new byte[1024];
File pdf = new File(context.getCacheDir() + "/" + filename);
if (!pdf.exists()) {
pdf.createNewFile();
FileOutputStream fOS = new FileOutputStream(pdf);
while (fileSize > 0 && (bytesRead = dIS.read(buffer, 0, (int)
Math.min(buffer.length, fileSize))) != -1) {
fOS.write(buffer, 0, bytesRead);
fileSize -= bytesRead;
}
dIS.close();
dOut.close();
}
pdfFile = pdf;
socket.close();
return pdf;

Java - Files get corrupted when sent over socket, except when sent to localhost

I'm trying to build a file server and file client program in Java using sockets, and I've been running into some issues when trying to send files from the server to the client. Below is the code that I use to send and receive files respectively:
private void sendFile(String filePath) {
try (BufferedInputStream fileInputStream = new BufferedInputStream(new FileInputStream(filePath))) {
BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());
byte[] buffer = new byte[4096];
while (fileInputStream.read(buffer) != -1) {
outputStream.write(buffer);
outputStream.flush();
}
}
catch (IOException e) {e.printStackTrace();}
}
private void downloadFile(String fileName, long fileSize) {
try (BufferedOutputStream fileOutputStream = new BufferedOutputStream(new FileOutputStream(downloadDir + "/" + fileName));
BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());
OutputStreamWriter writer = new OutputStreamWriter(new BufferedOutputStream(socket.getOutputStream()), "UTF-8");) {
writer.write("GET" + fileName + System.lineSeparator());
writer.flush();
long totalReceived = 0;
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
while (totalReceived < fileSize) {
inputStream.read(buffer);
int numOfBytesToWrite = fileSize - totalReceived > bufferSize ? buffer.length : (int)(fileSize % bufferSize);
fileOutputStream.write(buffer, 0, numOfBytesToWrite);
fileOutputStream.flush();
totalReceived += numOfBytesToWrite;
}
}
catch (IOException e) {}
}
The downloaded file does get created and seems to be of the right size, but always gets corrupted and cannot be opened by any program. However, this issue does not show itself when I run the client on the same machine and connect it to "localhost" or "127.0.0.1", then there are no problems and downloaded files are not corrupted. See any issues with my code?
In your sendFile() you need to consider the return value from the read() which may be less than 4096... This value should then be used in the write call to only write out the portion of the array that has been populated...
int bytesRead = 0;
while ((bytesRead = fileInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
outputStream.flush();
}
A similar problem occurs in downloadFile(), return from read() is the actual number of bytes read, some value less than or equal to 4096...
long totalReceived = 0;
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
while (totalReceived < fileSize) {
int bytesRead = inputStream.read(buffer);
fileOutputStream.write(buffer, 0, bytesRead);
fileOutputStream.flush();
totalReceived += bytesRead;
}
Why does your code work on localhost, but not over a network?
Atypical physical layer of a network is Ethernet, this will have a MTU of 1500 bytes. So you'll probably be seeing successive read() calls only filling 1500, or fewer bytes of your buffer...
However, localhost is optimized in the stack to bypass the physical layer which will not have this limitation. It is likely in this case successive calls will fill the full 4096 buffer, apart from the last, unless your file size is exact multiple of 4096.

Getting the full InputStream

I am working on a Web Server, I am stuck on the HTTP method PUT ... I currently can only bet 10 bytes of data from the client when he tries to upload a file, bellow is what I have so far.
InputStream stream = connection.getInputStream();
OutputStream fos = Files.newOutputStream(path);
int count = 0;
while (count < 10) {
int b = stream.read();
if (b == -1) break;
fos.write(b);
++count;
}
fos.close();
Please tell me how I can get the as much input the client writes.
You limited it to 10 by your while loop using 10. Since stream.read() returns -1 at the end of the stream, use that in the while loop as the control:
int count = 0;
int b = 0;
while ((b=stream.read()) !=-1)
{
fos.write(b);
count++;
}
public void receiveFile(InputStream is){
//Set a really big filesize
int filesize = 6022386;
int bytesRead;
int current = 0;
byte[] mybytearray = new byte[filesize];
try(FileOutputStream fos = new FileOutputStream("fileReceived.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos)){
//Read till you get a -1 returned by is.read(....)
bytesRead = is.read(mybytearray, 0, mybytearray.length);
current = bytesRead;
do {
bytesRead = is.read(mybytearray, current,
(mybytearray.length - current));
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
bos.write(mybytearray, 0, current);
bos.flush();
bos.close();
}
catch (FileNotFoundException fnfe){
System.err.println("File not found.");
}
catch (SecurityException se){
System.err.println("A Security Issue Occurred.");
}
}
Based on this one: FTP client server model for file transfer in Java

Packet loss in socket programming java

I am trying to send a file from client to server. Below is the code i have tried. But at times, there is a packet loss during the transfer. I am not sure where i am wrong.
SERVER SIDE CODE:
public static void ReadAndWrite(byte[] aByte, Socket clientSocket,
InputStream inputStream, String fileOutput)
throws FileNotFoundException, IOException {
int bytesRead;
FileOutputStream fileOutputStream = null;
BufferedOutputStream bufferedOutputStream = null;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try
{
fileOutputStream = new FileOutputStream( fileOutput );
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
bytesRead = inputStream.read(aByte, 0, aByte.length);
System.out.println("The length is "+bytesRead);
int count = 0;
do {
count++;
byteArrayOutputStream.write(aByte);
bytesRead = inputStream.read(aByte);
} while (bytesRead != -1);
System.out.println("The count is "+count);
System.out.println("The length is "+byteArrayOutputStream.size());
bufferedOutputStream.write(byteArrayOutputStream.toByteArray());
bufferedOutputStream.flush();
bufferedOutputStream.close();
clientSocket.close();
}
catch(Exception ex)
{
Logger.writeLog(ex,Listen.class.getName(), LogType.EXCEPTION);
throw ex;
}
CLIENT SIDE CODE:
public void readByteArrayAndWriteToClientSocket(
Socket connectionSocket, BufferedOutputStream outToClient, String fileToSend ) throws Exception
{
try{
if (outToClient != null)
{
File myFile = new File(fileToSend);
System.out.println(myFile.length());
byte[] byteArray = new byte[(int) myFile.length()];
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(myFile);
} catch (IOException ex) {
Logger.writeLog(ex, FileUtility.class.getName(), LogType.EXCEPTION);
throw ex;
}
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
try {
bufferedInputStream.read(byteArray, 0, byteArray.length);
outToClient.write(byteArray, 0, byteArray.length);
outToClient.flush();
outToClient.close();
connectionSocket.close();
return;
} catch (IOException ex) {
Logger.writeLog(ex, FileUtility.class.getName(), LogType.EXCEPTION);
throw ex;
}
}
}catch (Exception e) {
Logger.writeLog(e, getClass().getName(), LogType.EXCEPTION);
throw e;
}
}
There is no 'packet loss', just bugs in your code.
The canonical way to copy a stream in Java is as follows:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
If you know the number of bytes in advance and the sender must keep the connection open after the transfer, it becomes:
while (total < expected && (count = in.read(buffer, 0, expected-total > buffer.length ? buffer.length : (int)(expected-total))) > 0)
{
out.write(buffer, 0, count);
total += count;
}
Forget all the ByteArrayInput/OutputStreams and the extra copies. Just read from the file and send to the socket, or read from the socket and write to the file.
The sockets read method will return when its has obtained all the bytes you asked for, OR, when it stops receiving data from the network.
As transmission is often interrupted in any real network you need to keep issuing read calls until you have the number of bytes you want.
You need code something like this:
char [] buffer = new char[1024];
int expect = 1000;
int sofar = 0;
int chars_read;
try
{
while((chars_read = from_server.read(buffer[sofar])) != -1)
{
sofar = sofar + chars_read;
if (sofar >= expected) break;
}
}
catch(IOException e)
{
to_user.println(e);
}

Java Updating Program questions

I have a program that updates files on the computer using information sent by a server, using sockets. The way I had it worked, but i wanted to make it more intuitive, simpler, more reliable, etc. here is the previous code:
int filesize = 6022386; // filesize temporary hardcoded
int bytesRead;
int current = 0;
/**
* receive file
*/
try {
byte[] byteArray = new byte[filesize];
java.io.InputStream inStream = socket.getInputStream();
bytesRead = inStream.read(byteArray, 0, byteArray.length);
FileOutputStream fileOutStream = new FileOutputStream(
"C:\\Program Files\\AVTECH\\NPS\\Files\\bin\\NPS Game.txt");
BufferedOutputStream buffOutStream = new BufferedOutputStream(
fileOutStream);
current = bytesRead;
do {
bytesRead = inStream.read(byteArray, current,
(byteArray.length - current));
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
buffOutStream.write(byteArray, 0, current);
buffOutStream.flush();
buffOutStream.close();
inStream.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
socket.close();
}
as you can see, in the do, while loop, it is using the input stream to get the data. now that i've updated my program, i have the stream sending an object called UpdateObject, which holds the byte[] array along with the file directory. here is that code:
int filesize = 6022386; // filesize temporary hardcoded
int bytesRead;
int current = 0;
try {
byte[] byteArray = o.getFile();
java.io.InputStream inStream = socket.getInputStream();
bytesRead = inStream.read(byteArray, 0, byteArray.length);
FileOutputStream fileOutStream = new FileOutputStream(o.getPath());
BufferedOutputStream buffOutStream = new BufferedOutputStream(
fileOutStream);
current = bytesRead;
do {
bytesRead = inStream.read(byteArray, current,
(byteArray.length - current));
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
buffOutStream.write(byteArray, 0, current);
buffOutStream.flush();
buffOutStream.close();
inStream.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
now my question is this: how do i change it so instead of using the instream, to use just a byte[] object in the UpdateObject sent over the socket? i've done some google searching, but i dont feel like i know the right question to ask. any help would be great! thanks in advance!!!
By replacing most of your code inside the try catch block with:
FileOutputStream fileOutStream = new FileOutputStream(
UpdateObject.getDirectory()+"\\NPS Game.txt");
fileOutStream.write(UpdateObject.getBytes()); //this is the byte[] array
fileOutStream.close();
Hope this helps.

Categories