I am sending files to remote Android client from java server. I write the bytes using outputstream. On reading these bytes read() method keep trying to read bytes after the stream is ended. if I close the outputstream on server-side, read operation work fines. But I have to write file on the same socket again so can't close output stream any solution?
NOTE: MY CODE WORKS FINE FOR SHARING SINGLE FILE
CODE FOR WRITING FILE
public static void writefile(String IP, String filepath, int port, OutputStream out) throws IOException {
ByteFileConversion bfc = new ByteFileConversion();
byte[] file = bfc.FileToByteConversion(filepath);
out.write(file, 0, file.length);
out.close(); // i donot want to close this and how can I tell reading side that stream is ended.
System.out.println("WRITTEN");
}
Here Am I reading the file on Android :
public Bitmap fileReceived(InputStream is) {
Bitmap bitmap = null;
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "a.png";
String imageInSD = baseDir + File.separator + fileName;
// System.out.println(imageInSD);
if (is != null) {
FileOutputStream fos = null;
OutputStream bos = null;
try {
bos = new FileOutputStream(imageInSD);
byte[] aByte = new byte[1024];
int bytesRead;
int index = 0;
DataInputStream dis = new DataInputStream(is);
while ((bytesRead = is.read(aByte)) > 0) {
index = bytesRead + index;
bos.write(aByte, 0, bytesRead);
// index = index+ bytesRead;
System.out.println("Loop" + aByte + " byte read are " + bytesRead + "whree index =" + index);
}
bos.flush();
bos.close();
Log.i("IMSERVICE", "out of loop");
java.io.FileInputStream in = new FileInputStream(imageInSD);
bitmap = BitmapFactory.decodeStream(in);
bitmap = BitmapFactory.decodeFile(imageInSD);
Log.i("IMSERVICE", "saved");
// if (bitmap != null)
// System.out.println("bitmap is "+ bitmap.toString());
} catch (IOException ex) {
// Do exception handling
// Log.i("IMSERVICE", "exception ");
System.out.println("ex");
}
}
return bitmap;
}
Actually, I want to reset socket connection
Thanks in advance
You need to:
Send the length of the file ahead of the file. You can use DataOutputStream.writeLong() for that, and DataInputStream.readLong() at the receiver.
Read exactly that many bytes from the stream at the receiver:
while (total < length && (count = in.read(buffer, 0, length-total > buffer.length ? buffer.length : (int)(length-total))) > 0)
{
out.write(buffer, 0, count);
total += count;
}
E&OE
Actually I want to reset socket connection
Actually you don't want to do any such thing.
If i donot close outputstream the read operation on other side stuck on keep reading
That is because the client socket's InputStream is still waiting for the server to send some packets of data thus blocking your Main Thread.
Solution:
You can put each of your sending(OutputStream) and reading(InputStream) of packets of data from the socket to a Thread to prevent blocking your main thread when reading and sending.
Create a thread that reads the InputStream and another one for the OutputStream
Side note:
Don't try to close your outputStream that it cant be reopened again as the documentation is saying:
Closing the returned OutputStream will close the associated socket.
The general contract of close is that it closes the output stream. A closed stream cannot perform output operations and cannot be reopened.
Related
I am trying to communicate between two machines using socket programming.
What I basically need is both machines should be able to send and receive files. The code I am pasting below is not showing any error but the server side program seems to be running indefinitely, i.e., it is not terminating. It got stuck on the line marked with comment stuck here.
In this code, initially, server is sending the file named "file.txt" and client is receiving it and saving the file with name "copy.txt". Later client is sending a file named "file2.txt" and server is receiving and saving it with name "copy2.txt".
Can someone please tell me the error and suggest some improvements?
//server side code
import java.net.*;
import java.io.*;
public class server
{
public static void main (String [] args ) throws IOException
{
//sending file started
ServerSocket serverSocket = new ServerSocket(16167);
Socket socket = serverSocket.accept();
System.out.println("Accepted connection : " + socket);
File transferFile = new File ("/Users/abhishek/desktop/file.txt");
byte [] bytearray = new byte [(int)transferFile.length()];
FileInputStream fin = new FileInputStream(transferFile);
BufferedInputStream bin = new BufferedInputStream(fin);
bin.read(bytearray,0,bytearray.length);
OutputStream os = socket.getOutputStream();
System.out.println("Sending Files...");
os.write(bytearray,0,bytearray.length);
os.flush();
System.out.println("File transfer complete");
//socket.close();
//sending comleted
//receiving file started
int filesize=1022386;
int bytesRead=0;
int currentTot = 0;
byte [] bytearray1 = new byte [filesize];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("/Users/abhishek/desktop/copy2.txt");
//fos.flush();
BufferedOutputStream bos = new BufferedOutputStream(fos);
//bos.flush();
System.out.println("not moving ahead!!!");//program stucked here
bytesRead = is.read(bytearray1,0,bytearray1.length);
currentTot = bytesRead;
System.out.println("current"+currentTot);
do
{
bytesRead = is.read(bytearray1, currentTot, (bytearray1.length-currentTot));
if(bytesRead >= 0)
currentTot += bytesRead;
System.out.println("current"+currentTot);
} while(bytesRead > -1);
System.out.println("outside current"+currentTot);
bos.write(bytearray1, 0 , currentTot);
bos.flush();
//receiving complete
System.out.println("Receving file completed");
socket.close();
}
}
//client side code
import java.net.*;
import java.io.*;
public class client
{
public static void main (String [] args ) throws IOException
{
int filesize=1022386;
int bytesRead=0;
int currentTot = 0;
Socket socket = new Socket("localhost",16167);
byte [] bytearray = new byte [filesize];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("/Users/abhishek/desktop/copy.txt");
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);
System.out.println("current"+currentTot);
bos.write(bytearray, 0 , currentTot);
bos.flush();
bos.close();
System.out.println("receiving first file completed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
//sending file
System.out.println("sending second file started!");
File transferFile = new File ("/Users/abhishek/desktop/file2.txt");
byte [] bytearray2 = new byte [(int)transferFile.length()];
FileInputStream fin = new FileInputStream(transferFile);
BufferedInputStream bin = new BufferedInputStream(fin);
bin.read(bytearray2,0,bytearray2.length);
OutputStream os = socket.getOutputStream();
os.flush();
os.write(bytearray2,0,bytearray2.length);
os.flush();
System.out.println("sending second file completed!");
//sending complete
socket.close();
}
}
Does the System.out.println("not moving ahead!!!");//program stucked here line actually execute? if so, then the problem is that the InputStream.read() functions are blobking functions; they will stop execution of the program ("block") until they are able to complete.
From the JavaDoc for InputStream:
Reads up to len bytes of data from the input stream into an array of bytes. An attempt is made to read as many as len bytes, but a smaller number may be read. The number of bytes actually read is returned as an integer.
This method blocks until input data is available, end of file is detected, or an exception is thrown.
Since you aren't getting an exception, this means that when you call .read(), there is no data available to be read, and you program sits around waiting for data to read (that never arrives). You should check that your client program is actually sending the data in the first place.
I'd bet
bytesRead = is.read(bytearray1,0,bytearray1.length);
is where you're really getting stuck. The problem normally if you are stuck here is that the other side of the communication has not sent any data, there's nothing to read, and your thread is stuck waiting for it to send.
on your client side, you call
bos.close();
after sending the first message. This is going to cause the socket to close as well, which will throw an IOException on your server end, and because you are not catching the IOException, your server program will just exit.
How much socket experience do you have? If you are just beginning with sockets, you might want to check out the extensions I wrote around this, starting with ServerSocketEx and DataFetcher.
I'm putting together some code to download files from an HTTP address in Android. I'd like to support download resumption if the download fails mid way.
The output I get when starting the download, then killing the wifi connection and restarting again several times is the following:
Start size 0
Stop size 12333416
Start size 12333416
Stop size 16058200
Start size 3724784
I cannot understand why after the first resumption, subsequent file size readings of the partially downloaded file do not match.
Thanks in advance!
public void download(String source, String target) throws IOException {
BufferedOutputStream outputStream = null;
InputStream inputStream = null;
try {
File targetFile = new File(target);
currentBytes = targetFile.length();
Log.i(TAG, "Start size " + String.valueOf(currentBytes));
outputStream = new BufferedOutputStream(new FileOutputStream(targetFile));
// create the input stream
URLConnection connection = (new URL(source)).openConnection();
connection.setConnectTimeout(mCoTimeout);
connection.setReadTimeout(mSoTimeout);
inputStream = connection.getInputStream();
inputStream.skip(currentBytes);
// calculate the total bytes
totalBytes = connection.getContentLength();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) > 0) {
// write the bytes to file
outputStream.write(buffer, 0, bytesRead);
outputStream.flush();
currentBytes += bytesRead;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
// close the output stream
outputStream.flush();
outputStream.close();
}
if (inputStream != null) {
// close the input stream
inputStream.close();
}
Log.i(TAG, "Stop size " + String.valueOf(currentBytes));
}
}
There are two things you are doing wrong:
To resume download to file you should append, not rewrite the file. Use special constructor for output stream:
FileOutputStream(targetFile, true)
To request part of file from server you should use HTTP 1.1 property "Range". You can do it like this:
HttpURLConnection httpConnection = (HttpURLConnection) connection;
connection.setRequestProperty("Range", "bytes=" + currentBytes + "-");
I have a problem to send a file(not necessarily a txt file) over a socket.I have 2 classes:Server,Client.When I read from a socket output stream and want to write the bytes in a file,it looks working but when i open the file it has nothing.(corrupted showing the size=0 kb).I also want it to transfer all kind of file over a socket.I don't want to use appache commons net.
Here is my code
Server class
FileOutputStream toFile1 = new FileOutputStream(f);
BufferedOutputStream toFile= new BufferedOutputStream(toFile1);
BufferedInputStream bis=new BufferedInputStream(incoming.getInputStream());
byte[]buffer=new byte[2048];
int bytesRead=0;
while((bytesRead = bis.read(buffer)) >= 0)
{
toFile.write(buffer, 0, bytesRead);
}
toFile.close();
toFile1.close();
bis.close();
out.println("226 Connection Closed");
out.flush();
}
Client class
BufferedOutputStream output = new BufferedOutputStream(socket.getOutputStream());
byte[] buffer = new byte[60*2024];
int bytesRead = 0;
while ((bytesRead = input.read(buffer,0,60*1024)) != -1) {
output.write(buffer, 0, bytesRead);
}
The only way that can happen with that code is if you are sending a zero length file, or maybe reading from a file input stream that is already positioned at EOF, or else you are looking at the wrong file afterwards.
I am using following code for reading image file from socket. It reads all the bytes from server because size of file on server and android machine are same. When i open this file it does not open the file and generate error that is the file is corrupted or too large.
public Bitmap fileReceived(InputStream is)
throws FileNotFoundException, IOException {
Bitmap bitmap = null;
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "a.png";
String imageInSD = baseDir + File.separator + fileName;
System.out.println(imageInSD);
if (is!= null) {
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
fos = new FileOutputStream(imageInSD);
bos = new BufferedOutputStream(fos);
byte[] aByte = new byte[1024];
int bytesRead;
while ( true ) {
bytesRead = is.read(aByte);
bos.write(aByte, 0, bytesRead);
if ( is.available()==0)
break;
}
bos.flush();
bos.close();
// is.reset();
// here it give error i.e --- SkImageDecoder::Factory returned null
bitmap = BitmapFactory.decodeFile(imageInSD);
} catch (IOException ex) {
// Do exception handling
Log.i("IMSERVICE", "exception ");
}
}
return bitmap;
}
Don't use available() for this, it won't work reliably!
The docs state:
[ available() ] Returns an estimate of the number of bytes that can be read [...] It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream.
Do it like:
while ( (bytesRead = is.read(aByte)) > 0 ) {
bos.write(aByte, 0, bytesRead);
}
I got working over socket file sender, it worked perfectly, but I couldn't send large files with it. Always got heap error. Then I changed the code of client, so it would send file in chunks. Now I can send big files, but there is new problem. Now I recieve small files empty and larger files for example videos can't be played. Here is the code of client that sends file:
public void send(File file) throws UnknownHostException, IOException {
// Create socket
hostIP = "localhost";
socket = new Socket(hostIP, 22333);
//Send file
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
OutputStream os = socket.getOutputStream();
//Sending size of file.
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(file.getName() + ":" + userName);
byte[] arr = new byte[1024];
try {
int len = 0;
while ((len = dis.read(arr)) != -1) {
dos.write(arr, 0, len);
}
} catch (IOException ex) {
ex.printStackTrace();
}
dos.flush();
socket.close();
}
and here is the server code:
void start() throws IOException {
// Starts server on port.
serverSocket = new ServerSocket(port);
int bytesRead;
while (true) {
connection = serverSocket.accept();
in = connection.getInputStream();
clientData = new DataInputStream(in);
String[] data = clientData.readUTF().split(":");
String fileName = data[0];
String userName = data[1];
output = new FileOutputStream("C:/" + fileName);
long size = clientData.readLong();
byte[] buffer = new byte[1024];
// Build new file
while (size > 0 && (bytesRead = clientData.read(buffer, 0, (int) Math.min(buffer.length, size))) != -1) {
output.write(buffer, 0, bytesRead);
size -= bytesRead;
}
output.close();
}
}
You failed to write out the length of the file to the stream in the client:
long size = clientData.readLong();
So that call in the server is reading the first 8 bytes of the actual file and who knows what that quantity is. You don't have to read the length from the stream since you only wrote a single file. After reading the filename, and username (not very secure is it?) you can just read the stream until EOF. If you ever wanted to send multiple files over the same open socket then you'd need to know the length before reading the file.
Also your buffers for reading are way to small. You should be at a minimum of 8192 instead of 1024. And you'll want to put all .close() in a finally block to make sure your server and clients shutdown appropriately if there is an exception ever.