1

I"m trying to write a string to an OutputStream using

public  SSLSocket         mClient;
private BufferedOutputStream  mOutputStream;

....

mOutputStream = new BufferedOutputStream( mClient.getOutputStream() );

public synchronized void WriteString( String asciiString )
{
    mOutputStream.write( asciiString.getBytes() );
    mOutputStream.write( 0 );
    mOutputStream.flush();
}

....

WriteString( "BASEL ..." );

I successfully transmit a different string using this method, and then (in response to a message received over the stream) try to send the message above.

On this call, the write operation is flushing the buffer immediately after the "B" is written, resulting in two packets being sent over the stream. The first is a single character; the second contains the rest of the string. This worked correctly on Linux until a recent update of the server.

Is there any way to force the OutputStream or BufferedOutputStream to treat the write() as an atomic operation, or to not transmit until the flush()?

I have also tried

private DataOutputStream  mOutputStream;
mOutputStream.writeBytes(asciiString);
mOutputStream.writeByte(0);
mOutputStream.flush();

with the same results.

Alex
  • 11
  • 3
  • 1
    Stock OpenJDK `BufferedOutputStream` [only flushes on write when the buffer is full](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/io/BufferedOutputStream.java#l94). Is there anything written to the stream before `WriteString()`? What JRE does this run on? I cannot reproduce. – dhke Jun 28 '17 at 15:57
  • I'm running on Amazon Web Server. java version "1.6.0_41" OpenJDK Runtime Environment (IcedTea6 1.13.13) (amazon-1.13.13.1.77.amzn1-x86_64) OpenJDK 64-Bit Server VM (build 23.41-b41, mixed mode) This is the second message written to the stream. The first message was transmitted in a single packet using the same function. – Alex Jun 28 '17 at 16:03
  • As @dhke said, the buffered stream only flushes when buffer is full or when you call `flush()`. Since neither is the case after the `B`, it is not a problem with the buffered stream, or even a problem with Java. It is likely a problem with the OS, especially since you said it started after the OS was updated. – Andreas Jun 28 '17 at 16:10
  • I really appreciate your comments - and they line up with my understanding. Would the Java libraries not wait until the flush() until sending anything to the OS? – Alex Jun 28 '17 at 16:16
  • @Alex Yeah, but the flush only guarantees that the JVM is sending the data to the OS, not when the OS sends them. But sending a single octet in a packet when there's more data in the socket buffer seems weird. But remember there's also the SSL layer to consider. – dhke Jun 28 '17 at 17:14
  • I still have the problem, but I think I have narrowed it down to the SSL encryption by turning debugging on in my app. After doing the write there are two calls to [Raw Write]. The first is 37 bytes long and contains only the first character as the first byte, and then the second [Raw Write] contains the rest of the data. Maybe I must find a different encryption. – Alex Jun 29 '17 at 19:54
  • see https://stackoverflow.com/a/33360518/4454122 for the full explanation – Alex Jun 29 '17 at 20:03

1 Answers1

0

The problem was in the change in implementation of the CDC encoding in the SSLSocket. To avoid a security issue it always breaks the message after the first byte.

see stackoverflow.com/a/33360518/4454122 for the full explanation

Alex
  • 11
  • 3