1. It's not Nagle 2. Keren is right - Mostly. I did take care to have my client flush its output buffer after each write, so the server should have picked the same number of reads. After sending off my original query, I went for a long walk, and hit on the answer, which I just finished implementing. It's this: The listener thread, upon registering a client in the user table, allows the mux read thread to start collecting data. Despite the flush, and despite my pacing the client messages 1/2 a second apart, the header and the first few records get picked up. I grab the header and open the output file. All subsequent stuff goes to the output log file - apart from the first few entries. The oddball thing, is thereafter there is no apparent buffering of client data. The solution is quite simple: Have the Java client do a (blocking) read (of say, one byte) on the socket after sending the header. Have the server sent a single "sync" byte to the client immediately after opening the log file. And all works just fine. Apropos of reading a good book on TCP "kishkes" - I have Steven's 3 "Protocol" volumes: You need a year's sabbatical from work to read them ... I suppose that the moral of the story, is to prepare a query to the list, take a walk, and then send it to the trash basket. Just the exercise of formulating a problem like this for someone else to read often carries its solution ... Thanks for the replies. Daniel Feiglin wrote: > > This programming problebm is not specific to Linux; it can be reproduced under Unix >(e.g Solaris). > > Here is the scenario: I have a C++ server (a sort of logger, a bit like syslog) and >many Java clients. > > Each Java client sends the server a text header record which I'll describe in a >moment, and thereafter, user generated > text "log" records. Every client write() (using the output stream obtained from the >socket), is followed by a flush() > call, to ensure that each write() is indeed carried out. > > The header record, a comma delimited list, contains a file name, where I want the >server to throw out the subseqent > stuff on a per client basis. It contains other fields not pertinent to this query. > > The server is built in "classic" fashion: A listener thread, assigns each client a >file descriptor, and a multiplexed > read thread (using select()) > processes reads from the clients. I use standard pthreads (Write once, run many). > > When a Java client comes "on board", it first sends the header, upon which basis a >log file is opened by the server on > the client's behalf. All subsequent message from that client are recognized as log >messages and written to the client's > log file. > > When a client disconnects, the server detects it (as a zero length read buffer) and >cleanly closes the file and the > socket connection. > > I maintain a table of online client records, which uses standard pthread mutexes to >avoid a few simple potential > clashes. > > Now for the problem: > > When a client comes up, for some reason or other, the header and the first first few >log records are aggregated by TCP, > and appear on select() as a single read(). All subsequent client writes are picked >up correctly. I can vary the number > of initially aggregated records by reducing the select() timeout (but not setting it >to zero!). The worst results are > obtained, when I allow select() to block. > > If for example, I set the select() timeout to say, 1 sec and force the client to >sleep 2 secs after issueing the header, > I can make the problem "disappear", if for an obvious reason. > > 1. Why does TCP aggregate the first few records, and then "settle down" and behave >as expected? > > 2. Any suggested "fix"? > > If it is felt that this is somewhat off-topic, please reply directly to me. > > References: Stevens, UNP Vol 1, and APUE, syslog sources (for an example).
begin:vcard n:Feiglin;Daniel x-mozilla-html:FALSE adr:;;;;;; version:2.1 email;internet:[EMAIL PROTECTED] x-mozilla-cpt:;0 fn:Daniel Feiglin end:vcard