Socket SEND()

Fairlight fairlite at fairlite.com
Fri Nov 7 13:11:24 PST 2008


Only Nancy Palmquist would say something like:
> Thank you all for the recv() advice.  I was sending XML so I just
> collected data until the final tag was received and all started working.

This assumes you're not suffering data dropout.

> Now I notice that the send() side has similar issues, but I am not sure
> how to test that the file was completely sent.
>
> Programming goes like this:
>
> status=send(accept_handle,ry{"")
>
> if status ne instr(ry{"[**","[**","1")-"1" then I know I did not send the
> correct number of bytes.  I have error trapping for this.  But it is not
> triggered.

I'm not following.  Unless I'm reading that right, let's assume ry eq
"test".  Doesn't your code make it test[** and then check for [** at the
end?  That'll be positive no matter what the original variable is.  It's
been a long two days, so maybe I'm just missing something about that code,
but it doesn't seem right to me at first blush.

> The value of status was correct, so I closed the socket.  However, the
> data had not flowed back fully.  I added a SLEEP "1000" between the
> send() and the socketclose() and it started working.
>
> Is there a data related way to handle this?  I am worried that the SLEEP
> "1000" might not be long enough and it is wasting time if it is too long.

Make your protocol handshaking.  When you send something, before you send
the next discrete chunk of data, wait for an ack packet from the remote
side.  What many protocols do is build the size of the application level
packet size into the packet itself.  If you use up to 4 bytes to do this,
you can send way more than you'd ever theoretically attempt in a single
packet, if you encode the size into those 4 bytes properly.  So you -know-
your size should be the first thing in the packet contents.  Let's look at
an example:

\001xxxx\001packet_type\001packet_contents_here\001

So you know, from this example (shamelessly stolen and modified from a
1-byte size field to a 4-byte field to go from 256 character packet
limitations to a VERY LARGE limitation) that you receive ^A, then four
bytes that detail the size of the entire packet, then ^A, then a packet
type (a protocol I used to use, ForumNet/ICB used to use this), then ^A,
then the contents of the actual data segment, then a terminating ^A.  (Just
in case it's not obvious, \001 is ^A.)

What you do is pre-assemble the part from the second \001 forward to the
end of the packet, calculate the length, add 5, encode that value into the
4-byte storage space, and prepend that \001xxxx segment onto the packet,
then send the whole thing.

On the receiving end, when you receive a packet, you look at the first four
characters after the initial ^A, calculate your length, and read until
you've hit that length, and make sure the last thing you received at the
tail end of that -was- indeed a ^A.  That way you know if you suffered data
dropout somewhere and have hit a misaligned transmission.

So for packet types, you can have whatever you like.  You could have auth,
data, ack, nak, whatever you need.  Right?

So make it a part of the protocol that if you send a packet of type "data",
you should get back a packet of type "ack" before sending another packet
outbound.

Hence, a handshaking protocol.

With that in place, there's no guesswork involved.  You receive an ACK
packet and you know you're done.  If you don't, you handle it accordingly.

> On the receive side, I could check the data to make sure it was all
> there.  On the send() side if the number of bytes sent is not real, how
> can I tell how long to wait before closing the socket?

Well, I suggest first looking at the man page for send(2), as fP's send() is
99% likely merely a wrapper for that C function.  Make sure you know what
you're dealing with.

I also suggest using select() and making both client and server
non-blocking.  That way you can rely on the data stream and not wait
perpetually for an ACK packet that may never come.  If you use select()
with a timeout, you'll have timeout intervals, at the end of any of which
you can decide, "Okay, waited long enough, let's either close the socket,
or let's try a resend."

Something sounds like it's broken.  Possibly the connection.  By
definition, TCP ensures that packets are supposed to arrive in-tact, and in
order.  Barring network issues or program crashes, the application should
observe exactly that kind of behaviour.

Still, going with a robust protocol will help you work around problems
you're encountering and may yet encounter.

> I really appreciate any help, even if it does not relate to the filepro
> sockets.  You were all very helpful last time.

Well, the only assumption I'm making is that fP-Tech implemented select()
for the 5.6 sockets.  It's only half an assumption, as a reliable source
told me it had been implemented...I've just never seen the docs personally.

The rest is all just common app-level protocol development and use.
Hopefully it helps.

Bests,

mark->
-- 
"I'm not subtle. I'm not pretty, and I'll piss off a lot of people along
the way. But I'll get the job done" --Captain Matthew Gideon, "Crusade"


More information about the Filepro-list mailing list