I'm trying to invoke a method from another class that means I want to use serialization I make an object of method name and it's parameters and write it on a socket but when I want to make ObjectOutputStream I encounter with error "connection reset by peer: socket write error"
I searched for the possible reasons but I couldn't find any suitable answer
in the server side I didn't close the sockets or I didn't do any work to close that I don't know what happens then :-??
in the line:
ObjectOutputStream oos = (new ObjectOutputStream(os));
and my piece of code is this:
InvocationVO invo = new InvocationVO("showStart", treasure, round);
for (int i = 0; i < numPlayer; i++) {
OutputStream os = socket.get(i).getOutputStream();
ObjectOutputStream oos = (new ObjectOutputStream(os)); // this has error
oos.writeObject(invo);
oos.close();
os.close();
Client.getClients()[i].invoke();
}
thanks for your helps in advance!
You are writing to a connection that has already been closed by the peer. I find it hard to believe that didn't turn up in your search. The cause of the problem is firstly that you are closing oos, and therefore the socket, in this code, so (a) it won't run the second time, and (b) closing the socket causes the peer to get an EOS condition and close the socket, so (c) the second time you run this code you will run into at least two problems.
There is a third problem you haven't hit yet. You are creating a new ObjectOutputStream every time you run this code rather than using the same one for the life of the socket. Same goes for ObjectInputStream wherever you use it too. If you do what you are doing here you are liable to run into StreamCorruptedException: invalid type code.
Related
Hello stack overflow world, I've been struggling with the most straight forward and common problem within Java IO, for some time, and now need your help to tackle it.
Check out this piece of code I have in a try block, within a thread.run():
// connect to client socket, and setup own server socket
clientSocket = new Socket(serverHostname, CLIENT_PORT);
//send a test command to download a file
String downloadFileName = "sample.txt";
DataOutputStream dataOutputStream = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("Sending a request to download file : " + downloadFileName + " from user: Arsa node"); //todo: replace with node user later
dataOutputStream.writeUTF("D/sample.txt");
//close socket if host isn't detected anymore, and if socket doesn't become null suddenly
dataOutputStream.flush();
dataOutputStream.close();
System.out.println("****File has been sent****");
in = new DataInputStream(clientSocket.getInputStream());
byte[] retrievedFileData = new byte[8036];
if (in.readInt() > 0) {
System.out.println("Starting file download!");
in.read(retrievedFileData);
System.out.println("File data has been read, converting to file now");
//closing input stream will close socket also
in.close();
}
clientSocket.close();
2 Main questions that have been confusing me to death:
Why does dataOutputStream.close() need to be run for writeUTF to actually send my string to the server socket, I find that when I don't have dos.close(), data isn't retrieved on the other side, further because I close it, I no longer can read from the socket - as it seems the socket connection becomes closed when the Output Stream is previously closed...
What's a better way, following some sort of pattern to do this? For context, all I'm trying to do is write the filename I'm looking to download to my client, then read the response right away, which I expect to be bytes with the file, any error handling I will consider as a part of my development.
Overall, it shouldn't be complicated to write something to a socket, then read and ingest it's response...which doesn't seem to be the case here,
any help would be greatly appreciated! If the ServerSocket code snippet is needed I'm happy to share.
The observed behavior is just a side-effect of close(), as it calls flush() before closing to make sure any buffered data is sent. To solve your problem, you need to call the flush() method instead of closing.
This behavior is not unique to DataOutputStream: a lot of other OutputStream (or Writer) implementations apply buffering, and you will need to flush when you want to ensure the data is sent to the client, written to disk or otherwise processed.
BTW: The DataOutputStream and DataInputStream is for a very specific type of data serialization protocol that is particular to Java. You may want to consider carefully if this is the right protocol to use.
This problem really has me stumped. I'm sending images from a client to a server using ObjectOutputStream, but over time the java heap keeps growing. This eventually causes an OutOfMemoryError exception. After some online research, the reset method seems to be the only solution. Which is great, but using it causes an error: mark/reset not supported. The only page I could find on this was here:
https://stackoverflow.com/questions/38814424/how-can-i-get-an-objectinputstream-that-supports-mark-reset
I'm not really sure what to do with that page's answer.
Anyway, here's the server code:
ServerSocket vchatserver = new ServerSocket(6677);
Socket c1 = vchatserver.accept();
ObjectInputStream ois = new ObjectInputStream(c1.getInputStream());
while(c1.isConnected()) {
ImageIcon icon = (ImageIcon) ois.readUnshared();
ois.reset();
}
And now the client's code:
Socket vchatclient = new Socket(pub_serverName, 6677);
ObjectOutputStream oos = new ObjectOutputStream(vchatclient.getOutputStream());
while(vchatclient.isConnected()) {
ImageIcon img = new ImageIcon(webcam.getImage());
oos.writeUnshared(img);
oos.reset();
Thread.sleep(25);
}
The object input stream doesn't support mark/reset. But you don't need it. You don't need to call reset() on the input stream. ObjectOutputStream.reset() is sufficient.
The question you linked is irrelevant.
NB while (c1.isConnected()) is not a valid test for end of stream. You need to catch EOFException. Similarly while (vchatclient.isConnected()) will not protect you from IOExceptions when writing. This method only tells you whether you have ever connected this socket. It doesn't tell you anything about the current state of the connection.
is there a way of knowing when or whether the flush() method of a BufferedOutputStream thread has finished successfully? In my case I'm using it for sending a simple string through a java.net.Socket. In the following code, the flush() method is run in parallel with the BufferedReader.read() method and the socket output is immediately blocked by the input read resulting in something that resembles a deadlock. What I would like to do is wait for the output to end, and then start reading the input.
Socket sk = new Socket("192.168.0.112", 3000);
BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
bo.write(message.getBytes());
bo.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String line = br.readLine();
if (line.equals("ack")) {
System.out.println("ack");
}
sk.close();
Update
ServerSocket:
ServerSocket ss = new ServerSocket(3000);
System.out.println("server socket open");
while (true) {
Socket sk = ss.accept();
System.out.println("new connection");
BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String line = br.readLine();
System.out.println("received line: " + line);
BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
bo.write("ack".getBytes()); bo.flush();
sk.close();
}
Update:
#Global Variable - the reason that read was blocking the socket is that it was waiting for the \n, indeed. Using
bo.write("ack\n".getBytes());
instead of
bo.write("ack".getBytes());
made it work.
Regarding the initial question, is there a way of knowing if flush() method has finished successfully, #Stephen C provided the answer:
there is no way to know that based on the Socket or OutputStream APIs.
The normal way to get that sort of assurance is to have the remote
application send an "reply" in response, and read it in the local
side.
This "reply" is implemented in the code sample and it works.
Is there a way of knowing when or whether the flush() method of a BufferedOutputStream thread has finished successfully?
It depends on what you mean by "finished successfully".
The flush() method ensures that all unsent data in the pipeline has been pushed as far as the operating system network stack. When that is done, then you could say that flush() has finished successfully. The way that you know that that has happened is that the flush() call returns.
On the other hand, if you want some assurance that the data has (all) been delivered to the remote machine, or that the remote application has read it (all) ... there is no way to know that based on the Socket or OutputStream APIs. The normal way to get that sort of assurance is to have the remote application send an "reply" in response, and read it in the local side.
In the following code, the flush() method is run in parallel with the BufferedReader.read() method and the socket output is immediately blocked by the input read resulting in something that resembles a deadlock.
The code that you are talking about is basically the correct approach. The way to wait for the response is to read it like that.
If it is not working, then you need to compare what the client and server side are doing:
Is the server waiting for the client to send something more? Maybe an end of line sequence?
Did the server sends the response?
Did it flush() the response?
A mismatch between what the client and server are doing can lead to a form or deadlock, but the solution is to fix the mismatch. Waiting for some kind of hypothetical confirmation of the flush() is not the answer.
UPDATE
The problem is indeed a mismatch. For example, the server writes "ack" but the client expects "ack\n". The same happens in the client -> server case ... unless message always ends with a newline.
Your code is reading reader.readLine() . Are your writing \n when writing? You may want to append \n to the string your are writing.
I tried to reproduce your problem. First, I ran in to some kind of blocking state too, until I realized, I was using readLine at Server-side, too. But the message I was sending did not have a concluding \n. Therefore, the serversocket was still waiting at its InputStream without sending the client the ACK through its OutputStream. I think, #Global Variable is right.
i have written the following code to download file.
java.io.BufferedInputStream in =
new java.io.BufferedInputStream(new java.net.URL(url).openStream());
java.io.FileOutputStream fos = new java.io.FileOutputStream(filename);
java.io.BufferedOutputStream bout = new BufferedOutputStream(fos,1024);
byte[] data = new byte[1024];
int x=0;
while((x=in.read(data,0,1024))>=0)
{
bout.write(data,0,x);
}
if(filename.equalsIgnoreCase("table.csv"))
{
updateflag=true;
}
if(filename.equalsIgnoreCase("quotes.csv"))
{
quoteupdate=true;
}
bout.flush();
bout.close();
in.close();
Now, when a file named "table.csv" is passed as paramenter to download function, everything works smooth. Problem is when i try to download "quotes.csv" after i download "table.csv".
The exact calling is this:
url="http://ichart.finance.yahoo.com/table.csv? s=%5EBSESN&a=00&b=31&c=2011&d="+(month-1)+"&e="+day+"&f="+year+"&g=d&ignore=.csv";
updateflag=true;
downloadDB("table.csv",url);
System.out.print("quotes to download");
url="http://download.finance.yahoo.com/d/quotes.csv?
s=%5EBSESN&f=sl1d1t1c1ohgv&e=.csv";
if(candownload==true)
{
downloadDB("quotes.csv",url);
}
candownload=false;
I get error saying : Unrecognized Windows Socket error:0: JVM_BIND
Now i understand JVM_BIND is saying i have a process already attached to port 80.
However, i have closed all streams at the end of my function. Why is this happening then?
Thanks in advance
I don't have enough privileges to post comments so my apologies for providing an answer that may not get to the exact problem.
Leaving streams open won't necessarily cause this problem AFAIK. It's really caused by trying to bind a new Server Socket when one is already existing. So... maybe you should check to see if your code is trying to bind a new ServerSocket every time (with the same port) the download function is called. You really shouldn't need to do that. Bind once, and in the accept method spawn a new thread that does the download.
I'm working on a network app written in Java, using ObjectOutputStream and ObjectInputStream on top of Sockets to exchange messages. My code looks like this:
Sender:
ObjectOutputStream out;
ObjectInputStream in;
try{
Socket socket=new Socket(address, port);
socket.setSoLinger(true, socketLingerTime);
out=new ObjectOutputStream(socket.getOutputStream());
out.writeObject(message);
out.flush();
out.close();
}catch (variousExceptions)...
Receiver:
Object incoming;
try{
incoming=myObjectInputStream.readObject();
}catch (SocketException socketError)
{
if (socketError.getMessage().equals("Connection reset"))
{
//this is the exception I get
}
}
Sometimes the message goes through ok, but other times I get the marked exception instead of an object. Isn't flush supposed to force the message through to the other side? Am I somehow using the function incorrectly? Or is this some sort of bug in the underlying Java/OS network code?
Thanks!
UPDATE:
I've done some more snooping on this, and it seems to only happen when the system's resources are being taxed by something. I've not been able to replicate it outside the VirtualBox, but that could just be because the VirtualBox doesn't have many resources to begin with. I'll keep this question updated as I look into it further.
It turns out the issue was caused by Nagle's Algorithm; the output buffer is within the OS, so it wasn't affected by flush. The solution is to turn Nagle's Algorithm off using Socket.setTcpNoDelay(true), and buffer messages at the user level using BufferedOutputStream.
For my case, it's a silly problem but wasting me 4 hours.
Just have to use outStream.writeln(""); or outStream.write(mess + "\n");
Since reader.readLine() reads until it finds '\n' character. So write() alone won't work.
You should be able to send one object per connection.
To ensure resources are cleaned up in an orderly manner it is best to close the socket as well as the output stream.
close() will call flush so it should be redundant.
What happens if you don't set the SO Linger?
What is the actual exception you are getting?
It sounds like a firewall in one of the routers in the path from client to server is sending an RST for some reason. I don't believe there's anything wrong with your code. I tried to replicate the problem, but couldn't.
Connection resets can be caused by writing to a connection that is already closed at the other end. Detection can occur at the next I/O or a subsequent one, e.g. a read. In other words it can be caused by a bug in your application protocol. SO_LINGER won't help, don't mess with this.