Why my java socket can't end itself? - java

Here is my code snippet:
BufferedInputStream in = new BufferedInputStream(
server.getInputStream());
LittleEndianDataInputStream ledis = new LittleEndianDataInputStream(
in);
byte[] contents = new byte[1024];
System.out.println("45");
int bytesRead = 0;
String s;
while ((bytesRead = ledis.read(contents)) > 0) {
System.out.println(bytesRead);
s = new String(contents, 0, bytesRead);
System.out.print(s);
}
System.out.println("53");
After my client send the message to the socket, and the programme successfully print the result, but I can't print the 53, until I stop the client socket's connection. What should I do to deal with it? My client is an async socket. Thanks.

Your while-loop ends, when it gets an EOF and an EOF is sent from the writing side, whenever you either close the socket or - more graceful - shutdown the output.
So, in your case, your while-loop will end, when the sending side calls socket.shutdownOutput(). This closes just the output stream and puts an EOF at the end of the data.
I'm pretty sure this was discussed before, unfortunately I cannot find the question any more to just link. From the top of my head, the writing side should run the following code to close the connection gracefully:
// lets say the output stream is buffered, is namend bos and was created like this:
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
// Then the closing sequence should be
bos.flush();
socket.shutdownOutput(); // This will send the EOF to the reading side
// And on the reading side at the end of your code you can close the socket after getting the EOF
....
while ((bytesRead = ledis.read(contents)) > 0) {
System.out.println(bytesRead);
s = new String(contents, 0, bytesRead);
System.out.print(s);
}
System.out.println("53");
server.close; // <- After EOF was received, so no Exception will be thrown

Related

First two letters missing in file transfer in java

I am working on a client/server transfer protocol in java. The client is sending a simple text file, everything is going across the wire fine in wireshark, but once it gets to the server side, the first two letters are missing from the text file. I believe that it is overwriting the first buffer for some reason.
My goal is to make a while loop that reads the bytes in the buffer and then increments a count that'll place the next set of bytes....in the place if the ones already written
Here is the server's code that I currently have:
int bytesRead;
int current = 0;
InputStream in = s.getInputStream();
// Instantiating a new output stream object
OutputStream output = new FileOutputStream(myFile);
PrintStream stream = new PrintStream(output);
// Receive file 1024 bytes at a time
byte[] buffer = new byte[1024];
while ((bytesRead = in.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
System.out.println(output.toString());
}

Java Socket: unable to send response to client after sending file to server [duplicate]

This question already has answers here:
Java multiple file transfer over socket
(3 answers)
Closed 3 years ago.
I'm using Java Socket to send a file to server and then get a response back. The problem is every time i try to read the response from server, it makes the file-reading part of the server hang. I really need your help on what's going on here?
Here is SERVER code:
ServerSocket server = new ServerSocket(PORT);
Socket client = server.accept();
BufferedInputStream netInStream = new BufferedInputStream(client.getInputStream());
BufferedOutputStream netOutStream = new BufferedOutputStream(client.getOutputStream());
String outFileName = "output/test";
File outputFile = new File(outFileName);
if (!outputFile.exists()) {
outputFile.getParentFile().mkdirs();
}
FileOutputStream fileOutStream = new FileOutputStream(outputFile);
BufferedOutputStream bufOutStream = new BufferedOutputStream(fileOutStream);
// read file from client and save
int bytesRead = 0;
byte[] buffer = new byte[1024];
while ((bytesRead = netInStream.read(buffer)) > 0) {
bufOutStream.write(buffer, 0, bytesRead);
bufOutStream.flush();
Log.line("Bytes read: " + bytesRead);
}
// clean up file IO
// ...
// send response to client
netOutStream.write("File received by server".getBytes());
netOutStream.flush();
// clean up network IO
// ...
CLIENT code:
Socket client = new Socket(DOMAIN_SERVER, PORT_SERVER);
BufferedOutputStream netOutStream = new BufferedOutputStream(client.getOutputStream());
BufferedInputStream netInStream = new BufferedInputStream(client.getInputStream());
String inFileName = "input/test";
File file = new File(inFileName);
if (!file.exists()) {
client.close();
return;
}
FileInputStream fileInSream = new FileInputStream(file);
BufferedInputStream bufInStream = new BufferedInputStream(fileInSream);
// read and send file to server
int bytesRead = 0;
byte[] buffer = new byte[1024];
while ((bytesRead = bufInStream.read(buffer)) > 0) {
netOutStream.write(buffer, 0, bytesRead);
netOutStream.flush();
Log.line("Bytes sent: " + bytesRead);
}
// clean up file IO
// ...
// read response from server
StringBuilder res = new StringBuilder();
byte[] charBuf = new byte[128];
int msgBytesRead = 0;
while ((msgBytesRead = netInStream.read(charBuf)) > 0) {
res.append(new String(charBuf, 0, msgBytesRead));
}
Log.line(res.toString());
// clean up network IO
// ...
The flow is, client sends a file to server, server reads the file and saves to its local storage then the server sends a response string to client, the client reads the response and prints it out on the screen.
If the code is like above, the server will not exit the while-loop and hang, therefor the client second while-loop doesn't read anything and hang, too.
But if i comment/remove the client second while-loop, both programs run and no hang occurs. File transfer is also success.
Your expectation is that read returns with no data once the server is done sending the file. This expectation is wrong. read will only return with no data if the server has closed the TCP connection and the flush you show does not close the connections but only makes sure that all buffered data are written to the TCP connection.
This means the server can still send more data after the flush and that's why your client is hanging in the read and waiting for more data.

program hangs inside while loop for reading input stream from socket: Java

I have the following code to read an input stream from a socket connection:
private ByteBuffer toByteBuffer(BufferedInputStream is) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int l;
byte[] data = new byte[256];
while ((l = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, l);
}
buffer.flush();
return ByteBuffer.wrap(buffer.toByteArray());
}
In the first iteration of the while loop, everything goes fine and I am able to get the data into the buffer. But then it gets stuck at while ((l = is.read(data, 0, data.length)) != -1) {
I think (and I might be wrong) it is because it is waiting for more data from the socket, which is never going to come.
How do I handle this situation/hang?
As the BufferedInputStream method you are using does not block you get the situation that as soon as your InputStream does not have any data and is not closed you don't get a -1 but a 0.
This will send your method into an endless loop.
So for reading local streams it is better to check for read() <= 0 as you usually get the data fast enough.The best way is to make sure there is an eof by closing the stream.

damaged large file transfer

When I try to send a large file from server by splitting it, some of the packages don't arrive at the client... as you can see in the console output
http://s7.postimg.org/94yjfame3/error.png
the client receive only 19799.. bytes , and the server sent 62800.. bytes.
the code is too long to past here... but here are the basics:
// server side -> send data
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
byte[] somePackageInfo= new byte[500];
byte[] streamOut = new byte[20000];
while(getDataFromLargeFile(somePackageInfo,streamOut) != 0) {
out.write(somePackageInfo,0,500);
out.write(streamOut);
out.flush();
}
out.write(0);
out.flush();
// client side -> get data
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
byte[] somePackageInfo= new byte[500];
byte[] streamIn= new byte[20000];
while(true) {
if(in.read(somePackageInfo,0,500) == 0) break;
in.read(streamIn);
saveDataToLargeFile(somePackageInfo,streamIn);
}
I tried to slow down the transfer (sleep(500)) but only most of the packages arrived.
tried to remove the flush() but still only most of the packages arrived.
what causes this problem and how can i fix it?
Your copy code is wrong. You are ignoring the count returned by read, and assuming that it fills the buffer. It isn't required to do that. See the Javadoc.
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Use with any buffer size greater than zero, typically 8192. Use at both ends.
Adding sleeps is literally a waste of time.

sending image from java server to android app

I would like to send image file from java server to android app using this code:
Server(Java):
File file = new File("./clique.jpg");
FileInputStream stream = new FileInputStream(file);
DataOutputStream writer = new DataOutputStream(socket.getOutputStream());
byte[] contextB = new byte[4096];
int n;
int i = 0;
while ( (n=stream.read(contextB))!=-1 ){
writer.write(contextB, 0, n);
writer.flush();
System.out.println(n);
i+=n;
}
writer.flush();
stream.close();
android app:
DataInputStream reader = new DataInputStream(socket.getInputStream());
byte[] buffer = new byte[4096];
ByteArrayOutputStream content = new ByteArrayOutputStream();
int n;
int i = 0;
reader = new DataInputStream(socket.getInputStream());
while ( (n=reader.read(buffer)) != null){
content.write(buffer, 0, n);
content.flush();
}
Utility.CreateImageFile(content.toByteArray());
What I noticed is that in the android app n which is the number of read bytes is not 4096 while I am sending from server byte blocks of 4096 size,also I can not get n=-1 which is the end of stream,it blocks until I close the app then I get n=-1.
Regarding the number of bytes you read at a time has nothing to do with the number of bytes you write -it very much depends on the network conditions and will be variable with every chunk (basically as many bytes managed to be transmitted in short period of time between your reads as many you will get in the read chunk.
Regarding the end of stream - in your server code you have forgotten to close the output stream (you only close the stream which is input stream - you should also close the writer which in turn will close the underlying output stream.
Two comments:
1) I would really recommend to use Buffered Readers/Writers wrapping the writes/readers - the code you will get will be nicer and you will not have to create/manage buffers yourself.
2) Use try {} finally and close your streams in finally clauses - this is the best practice that will make sure that you will close the streams and free resources even in case of problems while reading/writing.
You got a problem in your android code:
while ( (n=reader.read(buffer)) != null) {
n can not be null.
Use writer.close() instead of writer.flush() after your loop on the server.

Categories

Resources