This question already has an answer here:
how to achieve transfer file between client and server using java socket [duplicate]
(1 answer)
Closed 9 years ago.
I’m trying to send files using sockets in Java. The problem is this:
suppose there is a file of 97kb. It gets about 95.8kb and waits for more, but the writer has sent all 97kb.
The reading:
FileOutputStream fout = new FileOutputStream(fl);
int counter = 0;
byte[] byt = new byte[8192];
BufferedInputStream bin = new BufferedInputStream(cli.InputStream());
int count = 0;
while((count = bin.read(byt)) > 0)
{
counter = counter + count;
Log.d("TINTERACT", String.valueOf(count) + " _" + String.valueOf(counter) + " _" + String.valueOf(size));
fout.write(byt, 0, count);
}
fout.flush();
fout.close();
while writing is:
System.out.println("Starting writing");
FileInputStream fIn = new FileInputStream(path);
byte[] byt = new byte[8192];
BufferedInputStream bin = new BufferedInputStream(fIn);
BufferedOutputStream bout = new BufferedOutputStream(ser.OutputStream());
int count = 0, countr = 0;
while((count = bin.read(byt)) > 0)
{
System.out.println(count);
bout.write(byt, 0, count);
countr = countr + count;
}
bout.flush();
System.out.println("sent " + countr + "End");
bin.close();
writer complete sends the bytes total while reader donot get all bytes and loop wait for it
Your receiver loop that reads from the socket won't terminate until the sender closes his socket.
Try using:
while((count = bin.read(byt)) != -1)
instead of:
while((count = bin.read(byt))>0)
Related
I am trying to transfer a file from server to client using Java and TCP, however on the client-side I am getting a socket closed exception, whereas the server has no errors when attempting to transfer the file. I am confused about this error because I did not close the socket before trying to read from it. The server accepts the connection and sends the file, but the client gets that error. Any suggestion?
The error is:
java.net.SocketException: Socket closed
Server thread's run function:
public void run() {
System.out.println("Service thread running for client at " + socket.getInetAddress() + " on port " + socket.getPort());
try {
File file = new File("hank.txt");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
OutputStream os = socket.getOutputStream();
byte[] contents;
long fileLength = file.length();
long current = 0;
long start = System.nanoTime();
while(current!=fileLength) {
int size = 1000;
if(fileLength - current >= size) {
current += size;
}
else {
size = (int)(fileLength - current);
current = fileLength;
}
contents = new byte[size];
bis.read(contents,0,size);
os.write(contents);
System.out.println("sending file..." + (current*100)/fileLength+"% complete!");
}
os.flush();
this.socket.close();
}catch(Exception e) {
e.printStackTrace();
}
}
Client receiving the file code:
System.out.println("Going to get the file...");
socket = new Socket(response.getIP().substring(1), response.getPort());
byte[] contents = new byte[10000];
FileOutputStream fos = new FileOutputStream("hank.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
InputStream in = socket.getInputStream();
int bytesRead = 0;
System.out.println("Starting to read file...");
while((bytesRead = is.read(contents))!=-1) { //the error points to this lin
bos.write(contents,0,bytesRead);
}
bos.flush();
bos.close();
in.close();
//
socket.close();
Input stream for this socket is available in variable in
InputStream in = socket.getInputStream();
So
Change is.read(contents)) to in.read(contents))
I am having trouble converse over socket using writeUTF("String") to client listen to the message using readUTF().
Up to now it worked as I wanted. However after adding codes for receiving file from the client i am not able to send any massage to the client. The code is the followings. It has been days to figure it out... Can anyone help me solve this issue? I appreciate your inputs :-)
// Client.java
String ack = in.readUTF();
println(ack); // "How do you do?"
String aack = in.readUTF();
println(aack); // HANGING FOREVER
// Server.java
Socket server = serverSocket.accept();
DataInputStream in = new DataInputStream(server.getInputStream());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
// CAN SEND MESSAGES
out.writeUTF("How do you do? "+ "\r\n");
out.flush();
// AFTER THIS SEGMENT CANNOT WRITE TO CLIENT ANYMORE
int bytesRead;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
byte [] byteArray = new byte [FILE_SIZE];
InputStream is = server.getInputStream();
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
bytesRead = is.read(byteArray,0,byteArray.length);
current = bytesRead;
do {
bytesRead =
is.read(byteArray, current, (byteArray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
bos.write(byteArray, 0 , current);
bos.flush();
System.out.println("File " + FILE_TO_RECEIVED
+ " downloaded (" + current + " bytes read)");
}
finally {
if (fos != null) fos.close();
if (bos != null) bos.close();
}
// WORKS ALRIGHT UP TO THIS PART
// PROBLEM BEGINS...
// CANNOT
// SEND MASSAGE ANYMORE
// CLIENT WAIT FOR MSG HANGING FOREVER
out.writeUTF("Can you hear?"+ "\r\n");
out.flush();
I'd recommend that you use an OutputStreamWriter, like
OutputStream out = ...;
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, "utf-16"));
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).
I have two files: a chat server and a chat client. The chat client is supposed to say that it wants to upload a file to the server. And then it uploads. However, right now, all of the messages are being sent / received properly, but when I try to get the file transfer, the only thing I get is a file with 0 bytes (which is at the path I specify inside of the server class.
Broken part of the chatclient class:
/**
* Sends a broadcast to the server
*/
public static void broadcast() throws IOException {
if (UserInput.getText() == "/upload") {
File myFile = new File (FILE_TO_SEND);
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = Socket.getOutputStream();
System.out.println("Sending " + FILE_TO_SEND + "(" + mybytearray.length + " bytes)");
os.write(mybytearray,0,mybytearray.length);
os.flush();
System.out.println("Done.");
}
System.out.println("" + UserInput.getText());
outputStream.println(UserInput.getText());
outputStream.flush();
}
Broken part of the server class:
if (input.contains("/upload")) {
byte [] mybytearray = new byte [FILE_SIZE];
InputStream is = csocket.getInputStream();
fos = new FileOutputStream(FILE_TO_RECEIVED);
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);
bos.write(mybytearray, 0 , current);
bos.flush();
System.out.println("File " + FILE_TO_RECEIVED + " downloaded (" + current + " bytes read)");
}
Your copy loop is nonsense. The canonical way to copy a stream in Java is as follows:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
where 'count' is an int, and 'buffer' is a byte[] array of length > 0. I usually use 8192.
You should try surrounding the broken code with try-catch block and print out the error message from the stack. this would give you a better idea of what is not working. It's not a solution, I know, but it's easier to find a solution if you know the exact problem.
I'm trying to transfer files between client-server if the file is bigger than 12MB than it sends by blocks otherwise it sends normally. my main problem is that everytime I transfer something it gets more bytes than the original one, and I need to use digest messages after I complete this so it wont work the way it is, and the other one is when I try to send a file by network the client reads the file to send faster than the server writes it so client closes the program closing the connection, corrupting the file. my transfer code is below:
this is the client transfer code:
if(fSize>maxfileSize){
totbLidos = 0;
byte[] fBytes = new byte[fBsize];
while(totbLidos < fSize){
int bRemain = (int) f.length() - totbLidos;
if(bRemain < fBsize){
fBsize = bRemain;
}
int bRead = tFile.read(fBytes, 0, fBsize);
tServidor.write(fBytes, 0, fBsize);
tServidor.flush();
if(bRead>0){
totbLidos+=bRead;
}
System.out.println("Total Bytes Lidos: " + totbLidos);
}
tFile.close();
System.out.println("Ficheiro enviado");
cliente.close();
}
else{
totbLidos = 0;
byte[] fBytes = new byte[fSize];
while(totbLidos < fSize){
int bRead = tFile.read(fBytes,0,fSize);
if(bRead>0){
totbLidos+=bRead;
}
tServidor.write(fBytes, 0, fSize);
System.out.println("Total Bytes Lidos: " + totbLidos);
tServidor.flush();
}
tFile.close();
System.out.println("Ficheiro enviado");
cliente.close();
}
}
server transfer code:
if(fSize > maxfileSize){
totbLidos = 0;
DataInputStream tFile = new DataInputStream(cliente.getInputStream());
BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(fName));
byte[] fBytes = new byte[fBsize];
while(totbLidos < fSize){
int bRemain = size - totbLidos;
if(bRemain < fBsize){
fBsize = bRemain;
}
int bRead = tFile.read(fBytes, 0, fBsize);
fos.write(fBytes);
fos.flush();
if(bRead>0){
totbLidos+=bRead;
}
System.out.println("Bytes lidos: " + bRead);
System.out.println("Total Bytes Escritos: " + totbLidos);
}
System.out.println("Ficheiro recebido");
fos.close();
tFile.close();
cliente.close();
servidor.close();
}
else if(fSize < maxfileSize){
totbLidos = 0;
DataInputStream tFile = new DataInputStream(cliente.getInputStream());
BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(fName));
byte[] fBytes = new byte[fSize];
while(totbLidos < fSize){
int bRead = tFile.read(fBytes,0,fSize);
fos.write(fBytes);
fos.flush();
if(bRead>0){
totbLidos+=bRead;
}
System.out.println("Total Bytes Escritos: " + totbLidos);
}
System.out.println("Ficheiro recebido");
fos.close();
tFile.close();
cliente.close();
servidor.close();
}
}
You are not writing the same number of bytes you read here.
fos.write(fBytes);
try using
fos.write(fBytes, 0, bRead);
In addition to #Peter Lawrey answer I suggest you to reuse Apache Commons IO API to avoid this kind of bugs in future:
IOUtils.copyLarge(InputStream input, OutputStream output, long inputOffset, long length)