Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Reading from a Socket's InputStream



Greg, thanks for responding.

I have a client/server application suite built using J2SE. The two
applications communicate using HTTP. The client connects to the server
using the high-level URL and HttpURLConnection classes. The server listen
for and services client requests using the low-level ServerSocketChannel
and SocketChannel classes. The problem I'd like some advice on occurs when
the server tries to read the content of a client's PUT (or POST) request.
...etc...

Does the server look like it's getting a chunked Content-Transfer-Encoding
header from the client?  If so, then you have to implement the chunked
protocol.  I thought of this mainly because of this statement:

* I can see from dumping the data to a console window that the content
being received is the end part of what is being sent. Stated the other way,
the part of the text that I'm sending that is not being received is the
beginning. So if the text being sent consists of 100 lines, for example,
I'm receiving something like the final 60 lines of that text on the
receiving end.

The headers that go out with the content are as follows...

content-type: text/menu
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.4.2_09
Host: 192.168.0.104:55914
Connection: keep-alive
Content-Length: 15932

I'm also wondering if the size of the POST or PUT content has an effect on
whether it works or not.  Do smaller transfers work?  Do they omit the same
size of initial material?  If so, I'd guess that something isn't being
buffered or sent properly on the client.  The Sun-standard
HttpURLConnection is extremely limited in what it can POST or PUT, and I
don't recall how well-behaved it is if you exceed its limited capabilities.

Sorry, I meant to mention in my initial posting that this error occurs with content sizes as short as 128 bytes. (Maybe smaller, but 128 was the smallest test I've run so far.) I've also tried my "real world" 15K as well as 1K, 2K and 5K and I always receive only part of the data.

You could use the 'tcpdump' command to see if the client really is sending
what it should be.  See 'man tcpdump' in Terminal.

Good point. I'll try that tomorrow and post what I find.

Another possibility is that something is screwy with the Channel support on
server-sockets, or something in that vein.  Or that you're simply not using
the ServerSocketChannel and/or its I/O streams correctly,  though I can't
tell without all the code.

This problem shows up in just the second HTTP request my application makes. I guess another point worth making is that the request that I'm having a problem with works fine in all other respects if I don't open an OutputStream on the client or InputStream on the server.

I realize your server-side code works when run on XP, but you don't say how
many CPUs you have, or what machine, or what OS versions, all of which may
be relevant.  In short, it might work on XP by accident, or by a
side-effect of the platform's implementation.  Or it might fail on Mac OS X
for side-effect ereasons.

The XP machines I have are both single CPU (single core) P4-HT. One runs at 1.8GHz, the other at 2.3GHz. They're both running XP-P2. The JVM I run under XP is 1.4.2_06. I'm running MacOSX 10.4.4 on a dual G5 2GHz with 2GB of memory. The problems I'm having when MacOSX is involved occur when I'm running both the stock 1.4.2 JVM and the final candidate of 5.0. 

Since it's easy to use the non-Channel ServerSocket class to listen and
accept() new connections, I suggest writing a simple server using that
older API and see if it works or not against your existing client.  There
are many examples you can crib ServerSocket code from, which a little
googling should turn up.  I've used that API many times and it works
consistently on Mac OS X, either same machine or different ones, with or
without CR-LF's, interop with XP or not, and with or without HTTP.

Generating sample code is something I was hoping to avoid, but may have to do if it's not otherwise obvious what's going on. As I'm sure you know, the code-base of real applications are often much more involved than sample code needs to be, even if most of the code is doing unrelated tasks.

The trick to writing an HTTP server is you have to be fastidious in how you
implement the HTTP protocol.  It's easy to get it wrong, and even tiny
mistakes or omissions can have big consequences.  Also, it's a lot easier
to implement HTTP 1.0 than 1.1, and when I've done HTTP servers in the
past, that's always where I start.

I know one thing that has worried me from the start is that the client code is using high-level HTTP connections while the server code is using low-level sockets. I was worried that getting these two sides to talk to each other might not be easy.

As a cross-check, have your client send a POST to Personal Web Sharing on
Mac OS X, which runs the Apache server.  Then hook it up to a simple CGI
diagnostic that tells you what it received.  It's pretty easy to serve
pages with Personal Web Sharing, and it's reasonably straightforward to
configure it to run CGI's.


* The problem occurs when 1) the client is running under MacOSX and the
server is running under Windows XP, 2) client = XP & server = Mac, or 3)
client = Mac & server = Mac. The problem does not occur if both client and
server are XP based -- whether on the same XP box or different ones.

Are you perhaps using println() to a socket?  Or perhaps using readline()
from a socket?  If so, then the problem may be that you're not sending
CR-LF line-terminators.

I'm not using println nor am I using Reader's. I'm converting my content data to a byte[] and then writing those bytes as a single call to the OutputStream's write() method. As on the reading side -- I get the Content-Length, create a properly sized byte[], then do a single read on the socket's InputStream's read() method.

All the above is little more than guessing and conjecture.  Posting small
fragments of code tells nothing about the surrounding context, and in
client-server communication, context is crucial.

If none of the suggestions works out, I suggest creating a well-isolated
test-case that consistently exhibits the failure, and making it available
as a URL.  Then post the URL to the list.  One possible side-effect is that
the process of creating a well-isolated fail-case leads to a recognition of
a subtle latent bug in one's original code.  I've done that a few times, so
ruthless simplication can have a reward.

If nothing I've said here rings a bell for anybody, then I'll post a sample case tomorrow or the next day.

Thanks again for your response.

- Sparky


 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Java-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/java-dev/email@hidden

This email sent to email@hidden



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.