Solved

Socket problem

Posted on 2004-08-03
41
976 Views
Last Modified: 2010-05-18
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
Comment
Question by:mayankeagle
  • 19
  • 8
  • 5
  • +4
41 Comments
 
LVL 30

Author Comment

by:mayankeagle
ID: 11701176
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
 
LVL 92

Expert Comment

by:objects
ID: 11701211
are you sure the buffering is not occurring at the server end
0
 
LVL 9

Expert Comment

by:mmuruganandam
ID: 11701576
if you are using buffering stream then use the flush method to ensure that your contents are flushed
0
 
LVL 30

Author Comment

by:mayankeagle
ID: 11701640
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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11701671
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
 
LVL 92

Assisted Solution

by:objects
objects earned 50 total points
ID: 11701711
OutputStreamWriter osWriter = new OutputStreamWriter ( ostreamClient, "UTF8" ) ;
osWriter.write ( sMessage ) ; // 'sMessage' is the String message to be sent
osWriter.flush();
0
 
LVL 9

Expert Comment

by:mmuruganandam
ID: 11701775
what's at ur .NET server end... is it buffered stream...
0
 
LVL 30

Author Comment

by:mayankeagle
ID: 11701850
At the .NET server, its a NetworkStream object.

Mick, I tried your code.... same result.
0
 
LVL 92

Expert Comment

by:objects
ID: 11701924
> 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
 
LVL 3

Expert Comment

by:JohnnyAffa
ID: 11701934
did you read inputstream before writing?
0
 
LVL 9

Expert Comment

by:mmuruganandam
ID: 11702207
which one happens first... is it the read operation or the write operation...
any idea...
0
 
LVL 9

Expert Comment

by:mmuruganandam
ID: 11702212
swap that call and try again... might work..
0
 
LVL 30

Author Comment

by:mayankeagle
ID: 11702247
>> 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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11702267
>> 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
 
LVL 13

Expert Comment

by:Webstorm
ID: 11702439
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
 
LVL 13

Expert Comment

by:Webstorm
ID: 11702462
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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11703279
>> 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
 
LVL 9

Expert Comment

by:mmuruganandam
ID: 11703563
now its time for your code here...
0
 
LVL 4

Expert Comment

by:alikoank
ID: 11704607
> 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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11712618
>> 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
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 4

Expert Comment

by:alikoank
ID: 11712693
>  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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11712705
>> 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
 
LVL 4

Expert Comment

by:alikoank
ID: 11712719
> ending the program

that may be the answer.
0
 
LVL 30

Author Comment

by:mayankeagle
ID: 11712790
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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11712795
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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11712806
>> 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
 
LVL 4

Accepted Solution

by:
alikoank earned 200 total points
ID: 11712876
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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11712958
>> 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
 
LVL 4

Assisted Solution

by:alikoank
alikoank earned 200 total points
ID: 11713003
> 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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11713036
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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11713043
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
 
LVL 4

Expert Comment

by:alikoank
ID: 11713108
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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11714011
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
 
LVL 4

Expert Comment

by:alikoank
ID: 11714044
>> 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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11715380
Sigh. Looks like no one's got more inputs?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 11734674
It's something to do with TCP/IP and expected newlines i think. Yes, that's a very woolly observation i know ;-)
0
 
LVL 4

Expert Comment

by:alikoank
ID: 11734893
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
 
LVL 92

Expert Comment

by:objects
ID: 11740598
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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11750382
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
 
LVL 13

Expert Comment

by:Webstorm
ID: 11750851
>> 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
 
LVL 30

Author Comment

by:mayankeagle
ID: 11762377
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

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
count8 challlenge 13 85
strCopies  challenge 17 73
Java array passed to SQL where clause 23 41
Java Jpanels and Jframe 8 20
Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now