Filetransfer over Socket in Java, wont go out of while-loop - java

I am trying to create a simple server-client-program where the user can upload and download files. I have got the Sockets and Streams to work, and I can upload a file to the server. But whenever one file has been uploaded the Server-side seems to get stuck in the loop that reads the streams and forwards it to the Server-file.
Server Code:
InputStream in = clientSocket.getInputStream();
String filePath = "......."
+ op[1];
System.out.println(op[0] + ": " + filePath);
FileOutputStream out = new FileOutputStream(filePath);
byte[] bytes = new byte[16*1024];
int count;
while ((count = in.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
Client Code:
String filePath = "...."
+ path;
System.out.println("Attempting: " + filePath);
dos = new DataOutputStream(serverSocket.getOutputStream());
fis = new FileInputStream(filePath);
byte[] buffer = new byte[4096];
while (fis.read(buffer) > 0) {
dos.write(buffer);
}
dos.flush();
fis.close();
The problem is that the program gets stuck at the while-loop, so the Server can not perform anything else. There are no errors or anything...

You never close the stream on the client side. Add dos.close() after dos.flush()!

Related

What is the accurate way to read/download a file from the server (in Java)?

In my client-server application I have used a command (GET filename)to download a file into the client side. I have used the build in read() method to read the file. My teachers said it's not a very good practice to implement this read method. The reason is either it doesn't tell how exactly the file is reading from the server or it somehow is not able to download dynamic (large) file size. But at the moment I see that it's working fine. Since I am still in intermediate level in java, I need to learn the best way to do this job. How it could be improved in coding? That is I want to improve the while looping part in ClientSide.
I have pasted the relevent code:
ClientSide:
............
............
if (request.startsWith("GET")) {
File file = new File(request.substring(4));
is = socket.getInputStream();
fos = new FileOutputStream(file);
byte[] buffer = new byte[socket.getReceiveBufferSize()];
int bytesReceived = 0;
while ((bytesReceived = is.read(buffer)) >=0) {
//while ((bytesReceived = is.read(buffer))>=buffer) {
fos.write(buffer, 0, bytesReceived);
}
request = "";
fos.close();
is.close();
}
.................
.................
ServerSide:
.................
.................
else if (request.startsWith("GET")) {
System.out.println("");
String filename = request.substring(4);
File file = new File(System.getProperty("user.dir"));
File[] files = file.listFiles();
if (fileExists(files, filename)) {
file = new File(filename);
int fileSize = (int) file.length();
outputToClient.print("Status OK\r\n"
+ "Size " + fileSize + "KB" + "\r\n"
+ "\r\n"
+ "File " + filename + " Download was successfully\r\n");
outputToClient.flush();
// reading files
fis = new FileInputStream(file);
os = socket.getOutputStream();
byte[] buffer = new byte[2^7-1];
int bytesRead = 0;
while ((bytesRead = fis.read(buffer))!= -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
fis.close();
} else {
outputToClient.print("Status 400\r\n"
+ "File " + filename + " not found\r\n"
+ "\r\n");
outputToClient.flush();
}
}
outputToClient.flush();
}
.................
.................
You need to consume the rest of the HTTP response headers, by reading until you get a blank line, if you haven't already done that.
Apart from that, your code looks fine to me, except that I would use a much bigger buffer than 127, at least 8192, possibly a multiple of that.
Ask your teacher what (on earth) he's talking about.

ZipOutputStream creating corrupt (unzippable) zip file

I am trying to send zipped bytes to another server and then have that server receive them and write out the zipped filed. When I do the zipping and writing on the same server it works great. The local version looks something like this:
ZipOutputStream zout = new ZipOutputStream(FileOutputStream);
zout.write(byteBuffer, 0, len);
zout.flush()
FileOutputStream.flush();
zout.close();
The cross server implementation creates a bad output though. The sending code is: (magic string tells the server it has received all of the data.
ZipOutputStream zout = new ZipOutputStream(out);
ZipEntry entry = new ZipEntry(fileName);
zout.putNextEntry(entry);
System.out.println("sending zipped bytes...");
zout.write(inputBuffer, contentBegin, len);
zout.flush();
zout.closeEntry();
out.flush();
byte[] magicStringData = "--------MagicStringCSE283Miami".getBytes("US-ASCII");
out.write(magicStringData, 0, magicStringData.length);
out.flush();
System.out.println("Done writing file and sending zipped bytes.");
Thread.sleep(10000);
zout.close();
clntSock.close(); // Close the socket. We are done with this client!
The receiving code looks like this:
System.out.println("receiving zipped bytes...");
byte[] inputBuffer = new byte[BUF_SIZE];
int total2 = 0, count = 0;
while(count != -1) { // read from origin's buffer into byteBuffer until origin is out of data
count = inFromCompression.read(inputBuffer, total2, BUF_SIZE - total - 1);
String msg = new String(inputBuffer, total2, count, "US-ASCII");
total2 += count;
if(msg.contains("-------MagicString")){
System.out.println("full message received...");
break;
}
}
String inputString = new String(inputBuffer, 0, total2, "US-ASCII");
int contentEnd = inputString.indexOf("--------MagicString");
FileOutputStream fout2 = new FileOutputStream(outputFileName + ".zip");
fout2.write(inputBuffer, 0, contentEnd);
fout2.flush();
fout2.close();
System.out.println("Done writing zipped bytes.");
//Thread.sleep(10000);
//socketToCompression.close();
Any ideas? I am thinking it might be something like I am not closing the ZipOutputStream before sending the magic string that signals the end of the data, but every time I call zout.close() immediately after flushing zout it closes the entire socket.
Get rid of the magic string and just send and receive the actual data. You're presently throwing away any buffer that contains the magic string, including whatever ZIP data may have been before it.
You don't need a ByteArrayOutputStream.

Client-Server not sending the entire file

When I run my client server - which is connecting and I try to send a file it doesn't won't send the whole file which is pulling errors else where, it gets about halfway through and constantly stops at the same part. This set up works when running the server-client on the same machine so I am completely confused
Server --->
// output (a DataOutputstream) is set up elsewhere and messages are sent and received properly
output.writeInt((int)file.length());
// send file
byte [] mybytearray = new byte [(int)file.length()];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
System.out.println("Sending " + file + "(" + mybytearray.length + " bytes)");
output.write(mybytearray,0,mybytearray.length);
output.flush();
System.out.println("Done.");
Client --->
// input (a DataInputstream) is set up elsewhere and messages are sent and received properly
String FILE_TO_RECEIVED = "Load_From.xml";
File file = new File(FILE_TO_RECEIVED);
int FILE_SIZE = input.readInt();
if(FILE_SIZE!=0){
// receive file
System.out.println("received file size : " + FILE_SIZE);
byte [] mybytearray = new byte [FILE_SIZE];
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = input.read(mybytearray, 0, mybytearray.length);
bos.write(mybytearray, 0, bytesRead);
You are only reading part of the data, both when reading the file and when reading the socket. The read method returns the number of bytes read, and you need a loop to read everything. For example,
int read = 0, offset = 0;
while ((read = bis.read(mybytearray, offset, mybytearray.length - offset) != -1) {
offset += read;
}
Or you can use classes from the standard library, for example DataInputStream has a readFully method.
DataInputStream dis = new DataInputStream(fis);
dis.readFully(mybytearray);
Please see the documentation of read() at: http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#read(byte[],%20int,%20int).
In particular:
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 means that if the length returned is not what you expect and you haven't encountered the end of file yet, you should call read() again (in a loop).

Send Receive multiple files over a socket [duplicate]

This question already has answers here:
Sending and receiving files on socket
(2 answers)
Closed 8 years ago.
Iv been unable to get this code to work after 2 days of trying everything I can think of. I am aware this exact question has been asked and answered but I am still unable to get mine working correctly. I am trying to send multiple files over a socket.
Iv modified the code to receive the file size before each receive but it still will not work correctly. I can get it to send all of the data into a single file but when I apply the while loops suggested in other posts it either only sends 1 file and then stops or nothing at all. Can someone please correct this if possible so I can move on. Its been almost a week since iv had this issue and even though I understand what I need to do I cant quite manage to get the syntax correct.
Any help would be appreciated.
Receive code:
private void receiveFile() throws IOException{
String fileToReceive = "test" + increment;
int bytesRead;
int current = 0;
DataInputStream inputs = new DataInputStream(connection.getInputStream());
long fileLength = inputs.readLong();
int total = 0;
//receive file
try{
byte [] mybytearray = new byte [(int)fileLength];
is = connection.getInputStream();
fos = new FileOutputStream(fileToReceive);
bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
while(fileLength > 0 &&(total = is.read(mybytearray, 0, (int)Math.min(mybytearray.length, fileLength))) != -1){
bos.write(mybytearray, 0, total);
fileLength -= total;
}
System.out.println("File " + fileToReceive + " downloaded (" + current + " bytes read)");
}finally{
// if (fos != null) fos.close();
// if (bos != null) bos.close();
// if (connection != null) connection.close();
}
increment += 1;
}
}
Send Code
public void sendFile(String file) throws IOException, ClassNotFoundException{
FileInputStream fis = null;
BufferedInputStream bis = null;
OutputStream dos = null;
DataOutputStream outputs = new DataOutputStream(connection2.getOutputStream());
try{
dos = connection2.getOutputStream();
File myFile = new File (file);
byte [] mybytearray = new byte [(int)myFile.length()];
outputs.writeLong(myFile.length());
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
dos.write(mybytearray,0,mybytearray.length);
System.out.println("Sent " + file + "(" + mybytearray.length + " bytes)");
dos.flush();
}catch(Exception ex){
ex.printStackTrace();
}
finally{
}
}
You have not provided the code which manages the Socket object itself, but it sounds like you are trying to re-open the socket, which is not possible. From the JavaDoc:
Once a socket has been closed, it is not available for further networking use (i.e. can't be reconnected or rebound). A new socket needs to be created.
Your best option is to keep the socket open and just flush it at the end of each file. You will then need a simple way to tell when a file ends (since the socket is nothing more but a string of bytes flowing between the two end points).
The easiest approach is to send the size of the file first in a predefined number of bytes (say 8 bytes to be on the extreme safe side). When sending a file, you send the 8 bytes first and then the content of the file. The receiver knows to expect this sequence, so it reads 8 bytes, parses them to figure out how many bytes represent the file and keeps reading the file until it reaches this number. Then, it start waiting for another 8 bytes.

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.

Categories

Resources