sclayton@wpi.WPI.EDU (Shawn A Clayton) (03/31/91)
I am having problems with TCP, write(), and read(). I want to send and receive 32 byte structures. The sockets used are of the type SOCK_STREAM, and I write() 32 byte chunks into one end (after connect()ing) and attempt to read() 32 byte chunks from the other end (after listen()ing and accept()ing). I write and read many of these 32 byte structures in succession. My problem is that if I do no put a sizeable delay in the send or receive loop, I end up receiving only part of a 32 byte chunk after a number of chunks have been received. There is no problem if I put in a large (the larger the better) delay before each write() or read(). I do not use the )_NDELAY or O_NONBLOCK options. Sometimes it will work with a given delay, and other times it does not. I seems to fail less the longer the delay is, and more the less the delay. It also fails more if the total number of chunks I attempt to send is increased. Below about fourty of these chunks there is no problem. Can anyone help me? What am I doing wrong? I would appreciate any comments or suggestions on what may be screwing this up. Please email me - Thanks - Shawn sclayton@ee.wpi.edu ----------------------------------------------------------------------- No, I don't have a signature line!
ted@blia.sharebase.com (Ted Marshall) (04/04/91)
The problem is that TCP is a pure stream protocol that does not preserve
record boundries. Thus, if something delays the processing on some of the
bytes from one of your write()s, your read can easily complete with only the
beginning of what we written.
Since you know that all "records" are 32 bytes, there is a real easy solution:
if your read() completes with less than 32 bytes, add that count to your
buffer pointer, subtract the count from your buffer size, and repeat the read.
Continue this loop until your buffer is full. For example:
ptr = &buffer[0];
cnt = sizeof buffer;
do
{
i = read(d, ptr, cnt);
if (i <= 0)
<error-processing>
ptr += i;
cnt -= i;
} while (cnt > 0);
--
Ted Marshall ted@airplane.sharebase.com
ShareBase Corp., 14600 Winchester Blvd, Los Gatos, Ca 95030 (408)378-7000
The opinions expressed above are those of the poster and not his employer.
0004219666@MCIMAIL.COM (Bob Stine) (04/04/91)
>I am having problems with TCP, write(), and read(). I want to send and >receive 32 byte structures.... >My problem is that if I do no put a sizeable delay in the >send or receive loop, I end up receiving only part of a 32 byte chunk >after a number of chunks have been received. Shawn, As you have discovered, TCP does not preserve record boundaries. One work-around makes use the value returned by read(), which is the number of the bytes read. Keep reading until you get your entire 32 bytes. I.e., int bf_ln, /* number of bytes requested */ bc, /* byte count returned by read() */ s; /* socket */ struct shawns_struct { /* whatever, 32 bytes worth */} in_rec; char *bptr; /* get the connection. Then, to load a structure... */ bf_ln = sizeof(struct shawns_struct); bptr = (char *) in_rec; while (bf_ln) { bc = read(s,bptr,bf_ln); if (bc < 1) exit(-1); bf_ln -= bc; bptr += bc; } Note that I exit if read() returns a value of zero. In BSD, select() will indicate that a closed socket is ready to read, but read() will return zero bytes. Hence, if the above loop didn't exit when read() returned a zero, then a closed socket would keep it busy for quite some time... :-) Regards, Bob Stine bstine@MCIMail.com