When I send only one object through a socket i am ok. But when i am trying to send two objects, i get
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source))
I have tried almost everything like flush() or reset() but none of them work.
public String SendObject(Object o) throws IOException {
OutputStream outToServer = client.getOutputStream();
ObjectOutputStream out = new ObjectOutputStream(outToServer);
out.writeUnshared(o);
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
return in.readUTF();
}
You're using an ObjectOutputStream to write the Object(s) from the client. You should be using an ObjectInputStream (not a DataInputStream) to read them on the server. To read two Objects might look something like,
InputStream inFromServer = client.getInputStream();
ObjectInputStream in = new ObjectInputStream(inFromServer);
Object obj1 = in.readObject();
Object obj2 = in.readObject();
Also, on the client, I think you wanted writeObject (instead of writeUnshared) like
ObjectOutputStream out = new ObjectOutputStream(outToServer);
out.writeObject(o);
While the other answers (e.g. #EJP's) are correct about the right way to send / receive objects and handle the streams, I think that the immediate problem is on the server side:
Exception in thread "main" java.net.SocketException: Connection reset
This seems to be saying that the connection has broken before the client receives a response. When the client side attempts to read, it sees the broken (reset) connection and throws the exception.
If (as you say) the sendObject method works first time, then I suspect that the server side is closing its output stream to "flush" the response ... or something like that.
You must use the same streams for the life of the socket, not new ones per send (or receive).
You need to decide between Object streams and Data streams. Don't mix them.
Don't try to mix between writeObject()/writeUnshared() and readUTF().
Related
I'm doing a comparison between some C functions used in network programming, and their Java counterpart. Most of them I can find in documents about Socket, ServerSocket, InetAddress classes.
However I can't seem to find listen(), recv(), send() and getaddrinfo() in Java. As far as I go, I see that most Java client-server programs do not require them, as you can just write the byte/message and flush them directly to the other end, using flush() or PrintWriter().
Do I understand this right, and are there any equivalent functions to those three?
When you create a ServerSocket, the underlying listen function gets called when you bind to a port, either through the constructor or though the bind method.
The recv and send functions are called by reading from and writing to the InputStream and OutputStream respectively that are attached to a Socket instance and returned by the getInputStream and getOutputStream methods.
Listening and receiving can be implemented in multiple different ways. Java is object-oriented so the logic is usually represented by a specific object type.
Take a look at Reading from and Writing to a Socket tutorial which gives a few examples on working with sockets, e.g. using InputStream and OutputStream to interact with Socket:
try (
Socket echoSocket = new Socket(hostName, portNumber);
PrintWriter out =
new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in))
)
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.
I have server
ServerSocket socketListener = new ServerSocket(Config.PORT);
...
client = socketListener.accept();
and client
sock = new Socket("127.0.0.1", Config.PORT);
I want to transfer between them some serialized data using ObjectInputStream and ObjectOutputStream.
When I try to do
ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
Nothing happens neither on the server side nor client side. Everything falls on that line. Both the client and the server is trying to get the input stream from the socket, but it does not work nor the client nor the server.
How do I solve this problem so that I can pass the serialized data between client and server?
As the javadoc says:
Creates an ObjectInputStream that reads from the specified InputStream. A serialization stream header is read from the stream and verified. This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.
So, since both the server and the client start by opening an InputStream, you implemented a deadlock: they both block until the other party has sent the stream header. If you start by opening an ObjectInputStream at client side, you must start by opening an ObjectOutputStream (and flushing immediately if necessary) at server-side (or vice-versa).
I'm writing a Java client/server application. It should allow clients to send text data to the server. This kind of communication should be repeatable many times using the same connection.
I write it like this:
// On a server:
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
socket.setKeepAlive(true);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
if (reader.ready()) {
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
// do something with line
}
}
// On a client:
Socket socket = new Socket(host, port);
socket.setKeepAlive(true);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.write("Some data from client to server");
writer.flush();
The problem is: I can't read on a server before I close OutputStream on a client. Or I can't open OutputStream on a client again, if it was already closed. How can I do continuous sending and reading of data?
You need two threads at both ends, one for reading data and other one for writing data.
The problem is: I can't read on a server before I close OutputStream on a client.
Yes you can. You just can't get to the case where readLine() returns null. It isn't the same thing.
Or I can't open OutputStream on a client again, if it was already closed.
Of course not. You have to create a new Socket.
How can I do continuous sending and receiving of data?
I don't understand the question. The code you posted doesn't attempt that.
If your goal is to send many mesages over the same socket connection, these messages will have to be delimited by an application-level protocol. In other words, you won't be able to rely on any system calls like reader.ready() or reader.readLine() == null to detect the end of the message on te server.
One way to achieve this is to begin each message with its length in characters. The server will then read exactly that number of charecters, and then stop and wait for a new message. Another is to define a special character sequence which concludes each message. The server will react to reading that particular sequence by ending the reading of the current message and returning to the "wait for new message" state. You must ensure that this sequence never appears in the message itself.
I got server-client application. On the client side, I am using this I/O stream to output data:
out = new PrintWriter(socket.getOutputStream(), true);
out.println("yeah");
On the server side I am trying to read the product by this line:
DataInputStream din = new DataInputStream(s.getInputStream());
String clientId = din.readUTF();
The server reaches the above statement and stops there. What's the problem? Are the two I/O streams not compatible with each other?
There are no exceptions thrown by either party, no output. I simply added System.out.println() before and after the above statement I=and I determined that the program does not cross this line:String clientId = din.readUTF();
You should use the DataOutputStream.writeUTF() method if you want to read from the other end of the socket with DataInputStream.readUTF(). See the Javadoc on DataInput for more detail on why. As an alternative, try using a buffered reader or scanner to read in your data.