I'm not really a programmer, as in I have no formal programming background, but I look at the world with programmers eyes, and I love the challenge of applying a language to problem solving. One of the hardest things for me is dealing with the assumed background I don't have. Assumed by the manuals and pods in a lot of cases. Currently I'm working on a mud, hoping to hone a few skills. As such I'm moving into new areas, the first of which is Unix sockets, so I'm intending to keep a set of notes for each new area I start to look at, to help me, and ulteriorly others, achieve their goals, should theirs resemble mine.
Don't you just love the way the pods give you nicely rounded examples which rapidly polymorph into congealed masses of subroutines as you try to apply them to real world situations. And, just as surely, any document about sockets will start out chanting the mantra of the theory behind client and server programming and understanding this information will stand you in as good stead as the pod code examples. You understand both but you still can't use the info absorbed to do what you want. Jargon of course is the main strainer, winnowing the blessed from the profane. I'll add more terms as I come across ones I've never met before.
Socket Jargon file
- techie jargon for "sleep".
- Out OF Band Data
- stuff trying to sneak in through the backdoor rather than the socket i.e. system signals, key interrupts.
- running and managing multiple sockets from one process
Socket ErrorsBy setting a socket to non-blocking, you can effectively "poll" the socket for information. If you try to read from a non-blocking socket and there's no data there, it's not allowed to block--it will return -1 and errno will be set to EWOULDBLOCK.
note that in C errno isn't a boolean return value, but rather a variable. Under perl the errors get passed to $!
When performing non-blocking I/O on sockets, be careful to check for the error EWOULD BLOCK (stored in the global variable errno), which occurs when an operation would normally block, but the socket it was performed on is marked as non-blocking. In particular, accept, connect, send, recv, read, and write can all return EWOULDBLOCK, and processes should be prepared to deal with such return codes. If an operation such as a send cannot be done in its entirety, but partial writes are sensible (for example, when using a stream socket), the data that can be sent immediately will be processed, and the return value will indicate the amount actually sent.
Socket error messages
- created by trying to open a port number below 1024 without having ROOT privs
- lack of memory(rare)
- unknown protocol
- no protocol for socket requested
- socket timeout
- socket request bounced
- ENETDOWN or EHOSTDOWN
- someone pulled the plug or cable somewhere else
- ENETUNREACH or EHOSTUNREACH
- someone pulled the plug or cable attached to the server
The error messages above are purely for reference, they seemed important after looking at "Chapter 12: Networking with Sockets" in "Advanced Perl Programming" just below where it describes an implementation of a multiplexing server
"In any case, once this operation is carried out, sysread and syswrite return undef (not 0) and set $! to EAGAIN (or EWOULDBLOCK on BSD 4.3)"
Left me to wonder what the fork EAGAIN and EWOULDBLOCK were. To be fair the whole thrust of the Black Cat book is to embed perl in C apps to get the best of both worlds, so the author didn't really count on a tech illiterate like me trying to grok him.
Helpful in dealing with this dearth of knowledge on my part were:
Beej's Guide to Network Programming
It's for C programmers but Perl uses the same libraries, in name anyway, so it's easy to follow, and hell I like the guys writing style.
An Advanced 4.4BSD Interprocess Communication Tutorial
Altogether a heck of a lot crustier than Beej in style, though still relevant (BSD and all that).
Of course while I was rooting about for these on the net didn't I just happen on Grahm Barr's presentation notes for a talk he gave on sockets. Hope he doesn't want them back :).
So the real skinny is to do with IO buffering. OSen use buffering to deal with delays that would be caused by direct read/write disc access, basically dealing with memory is faster than dealing with disc read/writes. This means there are various layers of buffering between your script and the OS. Normally a good thing, in the case of a network transaction it can cause "blocking", meaning one of the parties in a network dialog waits for their buffer to fill up, while really the rest of the script/process expects the data to have been sent.
In the above situation a multiplexing socket rather than waiting, will return an error stating the socket would block if it followed through with the operation.
Why look at low level socket programming when there are nice modules to help make this easierThis is true in part - with the pods for IO::Socket and IO::Select I had a working TCP socket in minutes, but there is absolutely no documentation for how to use the listed socket and select options. The reasons for this that I can think of are basically:
(1) you already know how to do it with low level sockets programming libs and any explanation would be superfluous, if not redundant.
(2) Giving examples of how to use these options goes beyond the scope of the pod, which isn't a socket FAQ or cookbook.