Writing to Socket outputStream w/o closing it - java

I'd like to write some messages to the server.
Each time, for the tramsmitting only, I'm closing the outputStream and reopen it when I have to send the next message.
os.write(msgBytes);
os.write("\r\n".getBytes());
os.flush();
os.close();
How Can I keep this Socket's OutputStream, os, open and still be able to send the message?
Thanks.

I am missing something here. If you don't call close, it will not close. For example,
os.write(msgBytes);
os.write("\r\n".getBytes());
os.flush();
// Do something
os.write("more message");
os.flush();
// When you are finally done
os.close();

In most protocols, the server accepts som kind of EOF symbol. Send such a symbol instead of closing the stream.
For example, IRC servers interpret "\r\n" as the end of a message. This would be 2 messages on one open OutputStream:
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.print("JOIN #channel1\r\n");
printStream.flush( );
printStream.print("JOIN #channel2\r\n");
printStream.flush( );
Also, you should wrap your outputStream with DataOutputStream. This wrapper creates more portable output. Plain OutputStream can cause trouble with certain primitive datatypes if server and client have different computer architectures.

Wrap the Socket's OutputStream in a PrintWriter and call the PrintWriter's println method.
PrintWriter pw = new PrintWriter(socket.getOutputStream());
....
pw.println(message); // call repeatedly to send messages.
....
pw.close(); // when finished writing to server and want to close conn.

I have found the problem and it lays on the client's side.
On the client, I have used -
count = inputStream.read(buffer)) > -1
That means, the client waits till server's outputStream closed, and then processing the incoming data.

Related

DataInputStream stuck when initialized

I have been trying to send a byte[] array across my client / server application using Sockets, DataInputStream and DataOutputStream, but on the server side, the program just gets stuck when I try to initialise the DataInputStream.
Here is the code on the client side (it works fine):
DataOutputStream datas = new DataOutputStream(connection.getOutputStream());
datas.flush();
byte[] send = identityKeyPair.serialize();
datas.write(send);
datas.flush();
Here is the code on the server side:
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()) );
sender = new PrintWriter(connection.getOutputStream());
newUser = new BasicUserData();
System.out.println("New registration from: " + connection.getInetAddress());
System.out.println("Data:");
String un = reader.readLine();
newUser.USERNAME = un;
System.out.println(newUser.USERNAME);
String pw = reader.readLine();
newUser.PASSWORD = pw;
System.out.println(newUser.PASSWORD);
DataOutputStream dataout = new DataOutputStream(connection.getOutputStream());
System.out.println("Opened data output stream");
DataInputStream receiver = new DataInputStream(connection.getInputStream());
//It gets stuck here, and the program doesn't read anything further
receiver.read();
byte[] id = receiver.readAllBytes();
System.out.println("Opened data input stream");
You are using both connection.getInputStream() and connection.getOutputStream() in two different ways. You should use one and only one way of reading from and writing to streams, don't mix multiple ways.
When you execute reader.readLine(), the BufferedReader called reader will read up-to 8192 characters from the input stream into its buffer, likely consuming all bytes your client has written. This means that when you construct your DataInputStream around that same input stream and try to read it, there is no data available to read, causing the receiver.read() to block waiting for data. That data is never received as your client has sent all its data, which is now buffered in reader.
In addition, unless your client has closed its output stream, InputStream.readAllBytes() will block indefinitely anyway, because it is only finished when the end-of-stream has been reached. And for socket communication, that only happens when the other side closed its output stream.
Change your code so there is only one way of writing data (though not relevant here), and one way of reading data. In addition, you should establish clearly how you need to read and write data in a protocol, so to avoid consuming too much data at the wrong point, and to know how much data you need to read when.
Of course it does nothing but wait as specified in the javadoc a call to DataInputStream#read() blocks the current thread until data can be read from the input stream.
Your reader = BufferedReader(...) uses the same underlying InputStream which means the all the data the client sent is most likely already consumed by the 'login' logic.
Since neither the client nor the server close their respective streams no EOF is emitted either which leads to the stream 'just dangling' around waiting for more data.
Unless your client sends more data the server will wait eternally.
There are two solutions for your issue.
Either thread you application so that the 'await input' logic is in it's own thread or take a look at javas NIO package (more precisely Channels and Selectors)

Java SSLSocket Outputstream message breaks

I have a problem, where a message I write to the OutputStream of a SSLSocket is send in multiple parts instead of one packet.
So, I have a SSLSocket:
final Socket newSocket = SSLSocketFactory.getDefault ().createSocket (server, port);
Since I connect to a special service, I manually send a non HTTP-standard connect header, which works just fine:
final OutputStream outputStream = newSocket.getOutputStream ();
outputStream.write (connect.getBytes ());
outputStream.flush ();
newSocket.setKeepAlive (true);
I then wait for a response, until I get a newline in it:
final InputStream inputStream = newSocket.getInputStream ();
final InputStreamReader inputStreamReader = new InputStreamReader (inputStream, "ISO-8859-1");
final BufferedReader bufferedReader = new BufferedReader (inputStreamReader);
I finish reading when I received a HTTP/1.1 200 Ok in a loop reading from the BufferedReader. Again, until this point everything is fine.
Then I begin using this socket to send messages from my own protocol like this:
outputStream.write (message.getBytes ());
outputStream.flush ();
When I now run a tcpdump on the target device, I can see that the socket connection is established and in fact two packets are send. Assuming the message would be Hello World, there is one packet which is marked as malformed, only containing the H. Then another one follows with the content ello World. No Exception is thrown during the run of this program.
Would could I possibly have done or missed to cause this kind of behaviour?
There are reasons for that I can not give you the complete code, but this question already contains all the significant passages.
Update:
As proposed in the comments, I tried to disable the Nagle algorithm using newSocket.setTcpNoDelay(true); just after creating the socket. But still, the packets sent are fragmented.

does close a socket will also close/flush the input/output stream

I have a program like that,
Socket socket = serverSocket.accept();
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
...some read and write here...
socket.close;
The code works fine. But I am not sure whether the in/out was close if I close the socket or not. Also I didn't call out.flush(), how the data going to be sent out?
Closing the socket doesn't flush the output stream but closes both streams and the socket.
Closing the input stream doesn't flush the output stream but closes both streams and the socket.
Closing the output stream flushes it and closes both streams and the socket.
You should close the outermost OutputStream you have wrapped around the one you got from the socket. For example:
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
DataOutputStream dos = new DataOutputStream(bos);
Close 'dos'. That flushes it, flushes 'bos', and closes everything.
Flush on close is documented in the Javadoc for FilterOutputStream.
Another answer: In Java, when I call OutputStream.close() do I always need to call OutputStream.flush() before?
says that yes! It will be flushed if you close it manually

Android - BufferedOutputStream doesn't flush

I have a problem with a BufferedOutputStream. I want to send a kml file from an Android device to a java server through a socket connection.
(The connection is ok, i am already able to exchange data with a PrintWriter in an other part of my program)
To send my kml file, I fill the buffer. But when i flush() it, nothing happen.
int lu = inFile.read();
while(lu != -1){
out.write(lu);
lu = inFile.read();
}
out.flush();
inFile.close();
inFile is my stream used to read the kml file
out is my BufferedOutputStream using the OutputStream of my socket
I don't close my out object but i don't want to, i don't use it just once. And this is the problem...
The close() method send the buffer's data but close the socket too.
The flush() method does not send the buffer's data.
I want to flush the buffer without closing my socket.
I also tried to use mySocket.shutdownOutput();
int lu = inFile.read();
while(lu != -1){
out.write(lu);
lu = inFile.read();
}
out.flush();
mySocket.shutdownOutput();
inFile.close();
This method close my stream and keep my socket open, that's what i want.
But when i try to open a new output stream, the Exception java.net.SocketException: Socket output is shutdown
So, how to flush my buffer without closing my sokcet are being unable to open a new output stream ?
Socket.close() and Socket.shutdownOutput() both send an EOS to the peer, on which he should close the socket, and after which you can no longer write to the socket, because you've closed it in that direction.
So if you need to continue writing to the socket you cannot use either of these methods.
Probably what you are searching for is a way to delimit application protocol messages. There are at least three techniques:
Send a length word prior to each message.
Send an out-of-band delimiter after each message, i.e. a byte or byte sequence that cannot occur in a message. The STX/ETX protocol, with escapes, is an example of this.
Use a self-describing message format such as Object Serialization or XML. STX/ETX is also an example of this.

Socket stream hangs when using IOUtils.copy()

I want to send an InputStream containing XML from the client to a server. Said server manipulates the XML stream using Streaming API for XML (StAX) and sends it back to the client.
I mange to send the XML to the server, the client receives the answer, but doesn't exit because the server never finishes reading the InputStream form the client.
But when the server is just dumping the input to System.out instead of sending something, reading finishes...
edit I forgot to mention that IOUtils.copy() is running in two separate threads on the client.
Here some code to reproduce this, I've replaced the StAX part with IOUtils.copy() on the server.
Server
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
IOUtils.copy(in, out);
Client
Socket socket = new Socket(host, port);
FileInputStream fin = new FileInputStream(file);
OutputStream out = socket.getOutputStream();
IOUtils.copy(fin, out)
InputStream in = socket.getInputStream();
IOUtils.copy(in, System.out)
You must flush and close InputStream and OutputStream.
like this:
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
IOUtils.copy(in, out);
//add
out.flush();
in.close();
out.close;
You are probably creating a deadlock.
Client - sends data to the server.
Server - loops data back to the client.
Client - reads data (that the server looped back)
So, while the client is sending data to the server, the server is sending it back to the client.
The client isn't reading that data, it's busy sending.
At some point the TCP buffers fill up, and the server blocks on sending more data to the client. This means the server is blocked on sending data, so eventually the TCP buffers on the receiving side of the server fills up as well, and the client blocks on sending data. Since the client is now blocked on sending, it'll never get to the part where it reads the data that is looped back, so the server will never un-block.
If you're sending a small document, you might not experience this, as all the data fits in the buffers, but once you fill up the buffers, the system will deadlock.
You have to multiplex the sending/receiving. e.g. you could start up a thread on the client that does
InputStream in = socket.getInputStream();
IOUtils.copy(in, System.out)
That way receiving can be done in parallel with the client sending data
Or you could use 2 threads on the server side. One for receiving the data, posting data to be sent back to another thread doing the sending (you'll have to build up an internal queue in this case between the threads).
As far as I remember IOUtils.copy() does not flush and does not close the stream. It seems that you do not call neither flush nor close too. Try it. I believe that this is your problem.

Categories

Resources