• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1026
  • Last Modified:

Socket problem

Hi folks :-)

I'm developing a Java client and a C# .NET HTTP server. What I've noticed is that when I send the first few bytes from the Java client to the server, it doesn't reach. When I send the next sequence of bytes, the first one reaches the server. Same way, when I send the third sequence of bytes, the second one reaches the server. I tried using flush () n' all. It still seems to be the same.

Any ideas why this is happening?

Thanks,
Mayank.

PS: Would post some code, if required.
0
Mayank S
Asked:
Mayank S
  • 19
  • 8
  • 5
  • +4
3 Solutions
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
Forgot to mention.... the C# HTTP server is actually like an HTTP listener which I've coded. It listens for HTTP messages of the format "POST/HTTP/1.1\r\n......".
0
 
objectsCommented:
are you sure the buffering is not occurring at the server end
0
 
mmuruganandamCommented:
if you are using buffering stream then use the flush method to ensure that your contents are flushed
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
Hi guys ;-)

I have to send a String in UTF-8 format, containing the HTTP message. So I use this:

ByteArrayOutputStream basData = new ByteArrayOutputStream () ;
OutputStreamWriter osWriter = new OutputStreamWriter ( basData, "UTF8" ) ;
osWriter.write ( sMessage ) ; // 'sMessage' is the String message to be sent
byte[] abData = basData.toByteArray () ;
ostreamClient.write ( abData ) ; // 'ostreamClient' is the socket's output-stream

Is there a better or simpler way?

I'm not using any buffered-streams/ writers here, but like I said, I've still tried calling flush () (on the output-stream of the socket, also on the byte-array output stream and the output-stream writer).

The buffering is not occuring at the Server end.
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
Also forgot to mention - initially, I was just testing the interop between sockets in .NET and Java, so I made them communicate by sending bytes from the Java client to the .NET server, and the bytes were transformed back into the original String sent by the Java client successfully. At that time, I just sent one message, and it worked.

Later, I modified the Java client-code to loop through, take some String as input from the user, and send it to the .NET server. The .NET server sends back response 'asychronously', so I made another thread which would be listening for response-messages from the server.

After adding this loop, the problem started. When I enter the first string as input, it doesn't show at the .NET server's console (though at the Java client, it shows as 'Sent'). When I send the second message at the Java client, it shows the first message at the .NET server, and so on.
0
 
objectsCommented:
OutputStreamWriter osWriter = new OutputStreamWriter ( ostreamClient, "UTF8" ) ;
osWriter.write ( sMessage ) ; // 'sMessage' is the String message to be sent
osWriter.flush();
0
 
mmuruganandamCommented:
what's at ur .NET server end... is it buffered stream...
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
At the .NET server, its a NetworkStream object.

Mick, I tried your code.... same result.
0
 
objectsCommented:
> Mick, I tried your code.... same result.

sorry, didn't expect it to fix the problem. Was just simplifying it for you, and reduce the memory requirements.

I suspect the buffering is at the server end.
0
 
JohnnyAffaCommented:
did you read inputstream before writing?
0
 
mmuruganandamCommented:
which one happens first... is it the read operation or the write operation...
any idea...
0
 
mmuruganandamCommented:
swap that call and try again... might work..
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
>> didn't expect it to fix the problem. Was just simplifying it for you, and reduce the memory requirements

Yeah ;-) I know.

>> I suspect the buffering is at the server end.

I use a .NET NetworkStream object there. I don't know if it is buffered by default. Will check it and let you know.

>> is it the read operation or the write operation...

The Java client writes to the socket first, then it receives a response asynchronously (I've kept another thread to monitor the input-stream and read the response).

>> did you read inputstream before writing?

I called getInputStream () first before getOutputStream (), if that is what you asked.
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
>> I don't know if it is buffered by default. Will check it and let you know.

But it works when I don't use threads. If I just send a single request string, and then wait for the response in the same thread, it works fine. When I start two threads (one taking input from the user and sending it to the server, and the other monitoring the input-stream, listening or response), the problem starts.
0
 
WebstormCommented:
Hi mayankeagle,

You may need to close the ByteArrayOutputStream before use toByteArray() method :

ByteArrayOutputStream basData = new ByteArrayOutputStream () ;
OutputStreamWriter osWriter = new OutputStreamWriter ( basData, "UTF8" ) ;
osWriter.write ( sMessage ) ; // 'sMessage' is the String message to be sent
osWriter.flush(); // <--
osWriter.close(); // <--
basData.close(); // <--
byte[] abData = basData.toByteArray () ;
ostreamClient.write ( abData ) ; // 'ostreamClient' is the socket's output-stream
0
 
WebstormCommented:
You may also have to verify your C# server is not reading through a buffered input stream waiting for a new line or a fixed amount of bytes.
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
>> You may need to close the ByteArrayOutputStream before use toByteArray() method

I did that. Not of help, though. I tried objects' approach which doesn't use a ByteArrayOutputStream at all. In that case too, the result is same. I thought its got something to do with flushing, etc, but I'm not using buffered-streams, at least at the Java end.

>> You may also have to verify your C# server is not reading through a buffered input stream

I used a NetworkStream.... it works fine with a C# client. Don't know if its buffered by default. Will find out.
0
 
mmuruganandamCommented:
now its time for your code here...
0
 
alikoankCommented:
> If I just send a single request string, and then wait for the response in the same thread, it works fine

That is exactly the answer to your problem.

TCP/IP system sends data to other computer using blocks. If you send some data, that is put into a buffer and send whenever a predetermined size is reached. If you send your data and then call "read" your data is send immediately.

That is how TCP/IP system works.

Built some kind of acknowledgement system into your protocol. Like:

COMP1              COMP2
SEND DATA-->
                  <--   ACK
SEND DATA-->
                  <--   ACK
...

In this way you can guarantee all your data is sent, and you will have the acknowledgement of the remote system.
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
>> If you send some data, that is put into a buffer and send whenever a predetermined size is reached

So we're talking of yet another level of buffering at the client-end, even after I have called flush () on my output-stream, at the protocol level itself. But why didn't that happen when I sent only one String and when I had no loop? 'coz the size of the block would've been same as the data being sent was the same.

Well, I cannot change the server-code now. Its built to send asynchronous responses, and so, it can't send back a response immediately. It sends it back after some time.
0
 
alikoankCommented:
>  But why didn't that happen when I sent only one String and when I had no loop?

That can happen if you wait for response after sending one string, or if you run both your client and server on the same box.

0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
>> That can happen if you wait for response after sending one string, or if you run both your client and server on the same box

I tried it with sending only one String and ending the program, without waiting for any response. It reached the server.
0
 
alikoankCommented:
> ending the program

that may be the answer.
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
The main code of the client-app is like this:

Socket sktClient = new Socket ( sIpAddress, iPort ) ;
SendThread thrSend = new SendThread ( sktClient ) ;
thrSend.getHandle ().join () ;
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
The SendThread class is like this:

public final class SendThread implements Runnable
{
  private OutputStream ostreamClient ;
  private ReceveThread thrReceive ;
  private Thread thrSender ;
 
  public SendThread ( Socket sktClient )
  {
    // initialize the data-members and start the thread

  } // end of constructor ()

  public Thread getHandle ()
  {
    return thrSender ;

  } // end of getHandle ()

  public void run ()
  {
    int iCounter = 1 ;

    // there is an enclosing try/ catch block here

    OutputStreamWriter osWriter = new OutputStreamWriter ( ostreamClient, "UTF8" ) ;

    while ( true )
    {
      // take input from the user

      // if the user types "EXIT", then break out of the while loop

      // form an HTTP message with the content being what the user entered

      osWriter.write ( sMessage ) ; // 'sMessage' is the String message to be sent
      osWriter.flush();

      // if iCounter is 1, then start the ReceiveThread (after sending the first message, get ready to listen for responses)

      // increment iCounter
     
    } // end while

    osWriter.close () ;
    ostreamClient.close () ;

  } // end of run ()

} // class definition over

I would post the skeletal code for the ReceiveThread, if you think it is relevant.
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
>> that may be the answer.

What is the solution, then, for an asynchronous handling of the response?

I am cutting out parts of the code which are not relevant (like taking input from the user, forming the message, etc) so that people don't run away seeing too long a code which takes time to read ;-)

Let me know if you want more code.
0
 
alikoankCommented:
you may try to use

PrintWriter out =
        new PrintWriter(
          new BufferedWriter(
            new OutputStreamWriter(
              sktClient.getOutputStream())),true);
.....

out.println(sMessage)

PrintWriter automatically flushes output when println called. I know that you are calling flush by hand, but nothing else comes to my mind.
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
>> PrintWriter automatically flushes output when println called

Yeah, it does if the constructor takes the second argument as 'true', but I guess that stands for 'flush-on-new-line'. If the String which is being sent itself contains several new-lines, will it flush after every new line (then it would be flushing in between sending of one message)? A typical HTTP message contains several new-lines. Will try it, though.
0
 
alikoankCommented:
> If the String which is being sent itself contains several new-lines, will it flush after every new line

no, it will not do that.
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
Guess what? The PrintWriter/ BufferedReader combination has always been my favourite for communication over sockets since years. I always made sure that I send a String with no new-lines (or if there were new-lines, the String would be broken-up at "\n" and sent as multiple strings through multiple calls to println ()).

In this very case, I did not use the PrintWriter particularly because I thought that it would flush after every new-line, whereas my message would itself consist of many new-lines, and I wanted it to flush only after the whole message is sent. So I used an output-stream writer. But well, I should've done a POC before concluding so. Now that I used my beloved PrintWriter ;-) the println () worked :-)

But hey, guys, does this mean that the flush () logic at the output-stream is flawed (I hate to think that way). It should flush it when I call it? That's what its meant for, right? I thought that the flush () logic at the PrintWriter was the same as the output-stream writer?
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
I'm waiting for an explanation to why the OutputStreamWriter's flush () didn't work. I'll split and close this one after that.
0
 
alikoankCommented:
When you send with osWriter.write(sMessage) your message is sent as it is, when you send with out.println a new line is added to your string. That should be the only difference between two calls.

I guess I am a bit late to admit that it may not be a flush() issue,  If only that newline character made the difference.

But since I cannot dig into JDK source right now, I have no way to explain this oddity.
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
Well, a new-line could be added.... but that should not answer the cause for flushing and not flushing, right? Especially when I am calling flush () explicitly while using the output-stream writer. The HTTP message anyway ends with new-lines.
0
 
alikoankCommented:
>> but that should not answer the cause for flushing and not flushing, right? Especially when I am calling flush () explicitly while using the output-stream writer.

The best way to find out why flush is not working at OutputStream level will be to look into JDK sources, which i do not have.

0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
Sigh. Looks like no one's got more inputs?
0
 
CEHJCommented:
It's something to do with TCP/IP and expected newlines i think. Yes, that's a very woolly observation i know ;-)
0
 
alikoankCommented:
I have downloaded JDK source today. PrintWriter synchronizes calls to all its output and flush methods. Below is an excerpt from PrintWriter.java source. Courtesy of SUN Corp. :-)

...
synchronized (lock) {
                     ...  
            out.write(lineSeparator);
            if (autoFlush)
                out.flush();
                     ...
}

...

that seems to be the only difference.
0
 
objectsCommented:
If you can create a small example that reproduces the problem (using a java server, and not .net) then I'll find some time to have a look at it for you.
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
Thanks for the offer, Mick. By the way, I wrote a similar Java server for this as you asked, which does exactly the same thing which the .NET server did. In this case, both the approaches (the output-stream writer and the print-writer) worked fine. I guess this is more of an issue with Java-.NET interop? Still wondering.... the plain-socket implementation at the bottom should be same.
0
 
WebstormCommented:
>> I guess this is more of an issue with Java-.NET interop?
Maybe you should post this question in the .Net area too.
http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/
0
 
Mayank SAssociate Director - Product EngineeringAuthor Commented:
Oh, bother :-) !

I guess I'm occupied enough with work, that I don't have time to follow much on this problem that much. As long as my beloved PrintWriter works ;-) will take this up later some other time.

Mayank ;)
0

Featured Post

Receive 1:1 tech help

Solve your biggest tech problems alongside global tech experts with 1:1 help.

  • 19
  • 8
  • 5
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now