HttpUrlConnection not connecting

Confirmed by packet-sniffing, the following code is not even opening a TCP/IP connecting:


URL submitScoreURL = new URL( "
http://192.168.1.119/incoming/scores" );
   
   connection = (HttpURLConnection) submitScoreURL.openConnection();
   connection.setDoOutput(true);
   connection.setRequestMethod( "POST" ); // has no effect if you remove this line
   
   System.out.println( "Sending score = "+score+" to remote host on connection = "+connection );
   XMLEncoder encoder = new XMLEncoder( connection.getOutputStream() );
   encoder.writeObject( score );
   encoder.flush(); // has no effect if you remove this line
   encoder.close();
   connection.getOutputStream().flush(); // has no effect if you remove this line
   
   System.out.println( "...sent" );

I … don’t understand :(. Surely there’s some stupid mistake I’m making here? :slight_smile:

I usually have this line in my post methods :

urlConn.setRequestProperty(“Content-Type”, “application/x-www-form-urlencoded”);

Borrowed from I don’t remember where, a long time ago…

Lilian :slight_smile:

also, firewall?

I dont use those silly personal-machine firewalls (partly because they make network development far too difficult :frowning: ), so the fact that no TCP/IP packets are generated mean its not a firewall problem :).

I think that you must read from the input stream, packet will only be sent when you will start reading inputstream.

EDIT: I mean you cannot only do an output because java HttpURLConnection will not sent output data since you try to read returned values, dont know why bugged implementation maybe.

ps: I am not sure that is true for all JVM

I seem to have found the problem. At least, I made a tiny change and now it works, but the change is so retarded I find it really hard to believe that was actually the problem :).

It seems that until you call:

(HttpURLConnection).getInputStream()

the class WILL NOT OPEN A CONNECTION NOR SEND ANY DATA.

So … all calls to e.g. flush() are completely ineffective until you open that inputstream. You may know that ther server is going to send no data in response to the post - but that tdoesn’t matter - you have to open the stream anyway.

This seems to me personally to be quite retarded, but … I merely added the call to getInputStream and suddenly it all started working :(.

NB: first thing I did was check the javadocs, and AFAICS none of this is documented. Current documentation (http://java.sun.com/j2se/1.5.0/docs/api/java/net/URLConnection.html et al) on java.sun.com doesn’t explain at all what the setDoOutput() method etc does, nor does it mention the absolute requirement for getInputStream to be called :(.

mutter mutter grumble frickin blocking-I/O programmers who don’t understand asynchronous I/O programming mutter grumble

Thanks! Glad to know it’s not just me that has experienced this :).

I’m no expert by any means, but doesn’t the HTTP protocol define a standard response to an HTTP request? Would there normally be at least an acknowledgment that the request was processed?

I agree that the implementation here seems rather dumb, but the HTTP/1.1 specification does state clearly in Section 6, “After receiving and interpreting a request message, a server responds with an HTTP response message.” … I don’t see where it says a response is optional, so the assumption that a response will be read is only half-stupid :slight_smile:

At the very least you should be getting back a “200” status response indicating that the request was “OK”

HTTP protocol just say “there will be a response” and not “you must read it”.

I cannot find any good reasons to wait that user read before sending data.

Annoyed by HttpURLConnection on a project a cupple of month ago, I had to make my own :frowning: because I was needing that data be sent as fast as possible.

I am not sure but I think the actual implementation of HttpURLConnection have also trouble with header Connection set to Keep-Alive (at least it had when I tried) wich can allow cool things : you may send in one thread while reading in another and so maintain an upload and a download channel open to an Http server.

The Keep-Alive isn’t neccessarily HttpURLConnection’s fault. BOTH servers need to be sending the header “Connection: Keep-Alive” header in order for the connection to stay open (plus they have to actually keep it open). not all servers want to do this. A quick telnet example shows:


c:>telnet google.com 80
GET /search?q=java-gaming.org HTTP/1.0
Connection: Keep-Alive <-- I sent a Keep-Alive header

HTTP/1.0 200 OK
Cache-Control: private
Content-Type: text/html
Set-Cookie: PREF=ID=1c8706f74edaa54f:TM=1144849891:LM=1144849891:S=5Mppdm-jbZlyK
kgj; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
Server: GWS/2.1
Date: Wed, 12 Apr 2006 13:51:31 GMT
Connection: Close <-- google doesn’t want to keep it open

the Connection header is borderline useless since HTTP 1.1 anyway. take a look at http://www.io.com/~maus/HttpKeepAlive.html for more information

back on topic now … generally, when it comes to doing HTTP work like this - especially with POST requests - it’s best to write your own class. The HTTP protocol is amazingly simple and isn’t worth going crazy over random errors like this. When I manually send headers through my own class, I never have to open any input stream first…

[quote]… BOTH servers need to be sending the header “Connection: Keep-Alive” header in order for the connection to stay open …
[/quote]
keepalive is a 1.1 feature and of course I was talking about HTTP 1.1 server not 1.0, also I had control over the server and so keep alive was allowed.

[quote]GET /search?q=java-gaming.org HTTP/1.0
[/quote]
you are sendind a 1.0 request :wink: not a 1.1

yes, it is quite simple to implement the http 1.0 protocol and it will works in most of case, it is harder to implement the 1.1 especially new features as chunk, keep-alive…

to perform a simple GET just open a socket on the remote server using the http port and send a string like the following:

GET /index.html HTTP/1.0 \n //\n == End of method line
\n\n //\n\n == End of headers

for 1.1 you will have at least to provide the header host to make the request valid, like that if your server is www.mysite.com

GET /index.html HTTP/1.1 \n //\n == End of method line
host: www.mysite.com\n
\n\n //\n\n == End of headers

  1. Yes, Keep-alive is crapped up in Sun’s implementation - you just can’t control it.

  2. Apache’s replacement for HttpUrlConnection has bugs in its keepalive that mean it doesn’t work properly

  3. If you have to impolement a custom protocol, HTTP is a great one. But if you don’t, HTTP is a bitch to implement, it has tonnes of features, especially if you want compatibility with “real” web servers and stuff that I do want like GZIP’d bodies :(. The spec is over 100 pages long, longer than many programming languages :).

  4. Bear in mind that, when used over the internet, HTTP gets mangled left, right, and centre by ISP’s. You do not want to be debugging your ISP’s shitty “clever” HTTP-moulding and caching, implemented by a sysadmin who thought they knew more than they did OR was more interested in saving the ISP money (reducing outgoing packets) than keeping the customers happy. Having been there and done that several times too many, I really dont want to implement my own HTTP client if I can possibly avoid it :).

all those things depend on your environment : http server local network or internet etc…, and you are right trying to reproduce a whole HTTP client to use over internet may be hard.

someone already done that for you

http://www.innovation.ch/java/HTTPClient/