Sending file from Server to Client java - java

When I'm sending a small file, everything works fine. But when I'm trying to send a file about 5 megabytes, server throws such exception: java.net.socketexception: connection reset by peer: socket write error.
This is a part of my Server:
try {
File myFile = new File("E:\\work\\java\\in.pdf");
long len = myFile.length();
byte[] mybytearray = new byte[(int) myFile.length()];
output = new PrintStream(serviceSocket.getOutputStream());
output.println(clientCounter + " " + len);
bis = new BufferedInputStream(new FileInputStream(myFile));
bis.read(mybytearray, 0, mybytearray.length);
os = serviceSocket.getOutputStream();
os.write(mybytearray, 0, mybytearray.length);
os.flush();
serviceSocket.close();
}
catch(IOException e) {
System.out.println(e);
}

You're assuming that read() fills the buffer, and no doubt you're making the same mistake in the client as well. You have to loop.

Related

IOException while trying to save output from ObjectInputStream to a file

I am new to the concept of working with streams and with files in Java.
I'm writing a piece of code, I have a very simple server that is listening for an incoming file.
Then I have a handler that deals with the incoming file.
Now, here is the code (stripped of try/catch blocks)
ObjectInputStream in;
in = new ObjectInputStream(new BufferedInputStream(
clientSocket.getInputStream()));
File f = new File(fileName);
int byteCount = in.readInt();
byte[] fileArray = (byte[]) in.readObject();
Files.write(f.toPath(), fileArray);
There comes an IOException when the program hits the ``byte[] fileArray = (byte[]) in.readObject();line. And - to be sure, theint byteCount` shows the correct number of bytes, the filename is also correct...
Stacktrace looks like this:
java.io.OptionalDataException
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1304)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at com.fileservice.util.ClientHandlerRunnable.run(ClientHandlerRunnable.java:85)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Code of the client sending the file:
Socket socket = new Socket(data.getIp(), data.getTcpPort());
FileInputStream fis = null;
BufferedInputStream bis = null;
// OutputStream os = null;
// send file
File myFile = new File(data.getFileName());
String test = myFile.getAbsolutePath();
byte[] mybytearray = new byte[(int) myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray, 0, mybytearray.length);
ObjectOutputStream os = new ObjectOutputStream(
new BufferedOutputStream(socket.getOutputStream()));
os.flush();
System.out.println("Sending " + data.getFileName() + "("
+ mybytearray.length + " bytes)");
if (os != null) {
os.writeInt(mybytearray.length);
os.write(mybytearray, 0, mybytearray.length);
os.flush();
System.out.println("Done.");
}
if (bis != null) {
bis.close();
}
if (os != null) {
os.close();
}
if (socket != null) {
socket.close();
}
You're sending raw bytes, and you're reading an object. That can't work. If you read an object, then the sender must have written an object (with writeObject()). If the sender writes bytes, then you must read bytes (with read()).
Note that your file reading section is wrong as well. read() gives no guarantee that it will read the number of bytes you ask it to read. You MUST use a loop to read everything. Or you can simply use Files.readAllBytes(), which will correctly read all the bytes from the file for you.

java tcp server to android device

i am trying to make a java server that will send images stored in a database to android device.
for now am trying with simple image that stored on the hard disk for the server to send.
my question is can i send an image from java server as a byte array to android via TCP sockets.
Yes, you can, using TCP sockets.
Read the file as bytes and send it as bytes, don't try to load it as a BufferedImage.
Then, on the receiving end, use a function that allows you to load an image from an array of bytes.
Sure, you can, but you will need to invent your own protocol for that. You may find using HTTP more, either setting up a web-server like Tomcat with your application deployed there, or use something embedded like Jetty
The fastest and easiest approach for sending image is as follows...
Try this
// Server Side code for image sending
ServerSocket servsock = new ServerSocket(13250);
System.out.println("Main Waiting...");
Socket sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
File myFile = new File ("\sdcard\ab.jpg");
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);*/
byte [] mybytearray =new byte[count];
System.arraycopy(Copy, 0, mybytearray, 0, count);
OutputStream os = sock.getOutputStream();
System.out.println("Sending...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
os.close();
sock.close();
servsock.close();
//Client side code for image reception
try
{
int filesize=6022386; // filesize temporary hardcoded
long start = System.currentTimeMillis();
int bytesRead;
int current = 0;
// localhost for testing
ServerSocket servsocket = new ServerSocket(13267);
System.out.println("Thread Waiting...");
Socket socket = servsocket.accept();
System.out.println("Accepted connection : " + socket);
System.out.println("Connecting...");
File f=new File("\sdcard\ab.jpg");
f.createNewFile();
// receive file
byte [] mybytearray = new byte [filesize];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream(f);
BufferedOutputStream bos = new BufferedOutputStream(fos);
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);
count=current;
Copy=mybytearray.clone();
bos.write(mybytearray, 0 , current);
bos.flush();
long end = System.currentTimeMillis();
System.out.println(end-start);
bos.close();
fos.close();
socket.close();
servsocket.close();
}
} catch(IOException e)
{
System.out.println("errorr");
}

how to stop socket keeps writing data in loop java

I have made server client application where server will send a file to client and client will receive it and save it in C:/ on any place.
I first send a string "File" in order to tell client to receive file and than server send file name and size to client and then start sending it.
Problem is that client doesnt receive file although it read in loop and get all bytes but doesnt write to required file object. Please have a look on client code I HAVE SHOWN WHERE IT STUCKS
Following is server code :
public void run(){
try{
System.out.println("Starting writing file");
objOut.writeObject("File");
objOut.flush();
File f= new File(filePath);
String name= f.getName();
int length =(int) f.length();
objOut.writeObject(name);
objOut.flush();
objOut.writeObject(length);
objOut.flush();
byte[] filebytes = new byte[(int)f.length()];
FileInputStream fin= new FileInputStream(f);
BufferedInputStream bin = new BufferedInputStream(fin);
bin.read(filebytes, 0, filebytes.length);
BufferedOutputStream bout = new BufferedOutputStream(objOut);
bout = new BufferedOutputStream(objOut);
bout.write(filebytes, 0, filebytes.length);
bout.flush();
System.out.println("File completelty sent");
}
catch(Exception ex)
{
System.out.println("error on writing file : "+ex.getMessage());
}
}
Following is client code :
while(true){
fobjIn = new ObjectInputStream(fileSock.getInputStream());
String str = (String) fobjIn.readObject();
if(str.equals("File"))
{
System.out.println("Starting receiving file");
ReceiveFile();
}
System.out.println(str);
}
public void ReceiveFile() throws Exception{
String name =(String)fobjIn.readObject();
File f = new File("C:/Temp/" +name);
f.createNewFile();
int length = (int) fobjIn.readObject();
FileOutputStream fout = new FileOutputStream(f);
BufferedOutputStream buffout = new BufferedOutputStream(fout);
byte[] filebyte = new byte[length];
int bytesRead=0,current=0;
bytesRead = fobjIn.read(filebyte, 0, filebyte.length);
do {
bytesRead = fobjIn.read(filebyte, current, (filebyte.length-current));
if(bytesRead > 0) {
current += bytesRead;
System.out.println("writting" + bytesRead);
}
else break;
} while(bytesRead > -1);
^^^^^^^IT DOESNT COMEOUT FROM LOOP while begugging^^^^^^^^
buffout.write(filebyte, 0 , current);
buffout.flush();
System.out.println("written");
}
You should probably close your stream on the server side when you are done sending, so that the client can be notified that the server is done sending. Or else it'll just sit there waiting for more data.

Differentiating between the data packets in TCP IP

I have a case where the server sends the file size first and the file data. How do I differentiate both the integer value and the file data when being read at the client side?
Sameple code for server (os is the bufferedoutputstream):
// Construct a 1K buffer to hold bytes on their way to the socket.
byte[] mybytearray = new byte[(int) myFile.length()];
//File Size
os.write((int) myFile.length());
FileInputStream fis = null;
System.out.println("test+sendbytes");
// Copy requested file into the socket's output stream.
try {
fis = new FileInputStream(myFile);
} catch (FileNotFoundException ex) {
// Do exception handling
}
BufferedInputStream bis = new BufferedInputStream(fis);
try {
bis.read(mybytearray, 0, mybytearray.length);
os.write(mybytearray, 0, mybytearray.length);
os.flush();
os.close();
os.close();
// File sent, exit the main method
return;
} catch (IOException ex) {
// Do exception handling
}
You need to write the length as an int unless you are assuming all files arfe no more than 255 bytes long. Try DataOutputStream.writeInt()
For the read you have to assume an order. ie you assume the length is sent first followed by the contents. Use DataInputStream.readInt() to read the length.

Socket-transferred file: contents are empty

I am working on transferring a file between two computers over a socket. Everything seems to work, but when I look at the contents of the retrieved file, it is empty. What am I doing wrong?
Here is my server-side code. The file foobar.txt exists, and its contents are "hello world!".
try{
ServerSocket ssock = new ServerSocket(12345);
Socket sock = ssock.accept();
//here I get the filename from the client, but that works fine.
File myFile = new File("foobar.txt");
byte[] mybytearray = new byte[(int) myFile.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
bis.read(mybytearray, 0, mybytearray.length);
OutputStream os = sock.getOutputStream();
os.write(mybytearray, 0, mybytearray.length);
os.flush();
sock.close();
} catch (Exception e){
e.printStackTrace();
}
And here is my client code:
try {
Socket socket = new Socket(host, port);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.print("get foobar.txt\r\n");
out.flush();
byte[] streamIn = new byte[1024];
InputStream in = socket.getInputStream();
FileOutputStream file_src = new FileOutputStream("foobar.txt");
BufferedOutputStream file_writer = new BufferedOutputStream(file_src);
int i;
while ((i = in.read()) != -1) {
file_writer.write(i);
}
file_writer.flush();
file_writer.close();
file_src.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
Solved
Since I am using multiple threads and multiple sockets and testing all connections on one machine, I was simply running into a problem where the client (which has both the client and server code in it) would connect with itself instead of the other client. Changing the file transfer port for the different running clients got this all to work. Thanks for everyone who had a look at this and gave me some suggestions.
Maybe you're closing the wrong socket on the client. When you close the socket, you're closing the class field this.socket instead of the local variable socket.
Also, when you close the output stream to the file, you don't have to close both the BufferedOutputStream and the FileOutputStream. The FileOutputStream is automatically closed when the BufferedOutputStream is closed.
One more thing---you don't have to flush an output stream before closing it. When you call close() the stream is automatically flushed.
In addition to what everyone else has said, you are ignoring the result of bis.read(). It isn't guaranteed to fill the buffer. See the Javadoc.
The correct way to copy streams in Java, which you should use at both ends, is this:
byte[] buffer = new byte[8192]; // or whatever
int count;
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
The only thing I think of that is that you actually never start receiving the file because the server-side doesn't read the command ("get foobar.txt"), so the client-side freezes on sending the command.
The existence of the file at the client-side might be from previous tests.
But, I'm not sure this is the problem. It's just a try to help.

Categories

Resources