A.J.Rasiah@massey.ac.nz (Ajit Rasiah ) (01/31/91)
Hello! I am trying to use the out-of-band (OOB) facility of UNIX sockets. I tried a send(s, "out of band data", 16, MSG_OOB); /* 1 */ write(s, "string 2", 8); /* 2 */ When I perform a read() I get the string "out of band dat". It appears that the string "out of band dat" (note the missing last character) is considered low-priority, and the logical mark identifying the start of the urgent data is in fact the missing last character (the 'a'). This implies that the string "string 2" is actually the urgent data! Why is this? What I want, is to be able to read the urgent data separately from the low-priority without mixing them up. What is the best approach I should use? Please reply to A.J.Rasiah@massey.ac.nz Thanks in advance.
sean@ms.uky.edu (Sean Casey) (02/01/91)
To receive out-of-band data, don't do a read(). Do a recv() with the OOB flag set. Things will work properly then. Sean -- ** Sean Casey <sean@s.ms.uky.edu>
enag@ifi.uio.no (Erik Naggum) (02/01/91)
In article <483sis-d@massey.ac.nz>, Ajit Rasiah writes: I am trying to use the out-of-band (OOB) facility of UNIX sockets. I tried a send(s, "out of band data", 16, MSG_OOB); [1] write(s, "string 2", 8); [2] When I perform a read() I get the string "out of band dat". It appears that the string "out of band dat" (note the missing last character) is considered low-priority, and the logical mark identifying the start of the urgent data is in fact the missing last character (the 'a'). This implies that the string "string 2" is actually the urgent data! Why is this? What I want, is to be able to read the urgent data separately from the low-priority without mixing them up. What is the best approach I should use? I'm posting this to the group to air a suggestion. The out of band facility was not intended to be used as a separate data channel. If you wish to multiplex two channels on one connection, I suggest that you do something like this: #include <sys/types.h> #include <netinet/in.h> struct mux { u_short channel; u_short datalen; }; [1] int muxwrite (int fd, u_short channel, void *data, u_short count) { struct mux xmit; xmit.channel = htons (channel); xmit.datalen = htons (count); write (fd, &xmit, sizeof xmit); [2] return write (fd, data, count); [3] } int muxread (int fd, u_short *channel, void *data, u_short *count, u_short max_count) { struct mux recv; read (fd, &recv, sizeof recv); [4] *channel = ntohs (recv.channel); *count = ntohs (recv.datalen); if (*count > maxcount) { } [5] return read (fd, data, *count); [6] } NOTE: This is not anywhere near finished, polished code. You need to figure out how to deal with a failure of the write in [3] when the write in [2] succeeded, because the read in [4] will expect a block of data following the "protocol portion". You would definitely do some sanity checking on the received channel and datalen elements, etc. There are problems to be solved in what you want to do when the test in [5] succeeds. There are also a few problems to be solved in what to do if the return value of the read in [6] is less than what is reported by *count. It should probably loop, slurping up bytes until the prescribed number of bytes are received. A checksum could be provided with [1]. You should probably devise a scheme by which these protocol portions are introduced so that you can detect when or if screw-ups occur in the protocol, e.g. by using a special magic value in [1] which is allowed only at the head of the protocol data unit ("packet"), and escaped when found in the data, much like SLIP does. I think I have made an excellent argument against using only one stream, and thus an equally excellent argument for two or more streams, which you alternate between via the select(2) system call. In fact, I suggest you do just that, instead of relying on long strings of out of band data. -- [Erik Naggum] Snail: Naggum Software / BOX 1570 VIKA / 0118 OSLO / NORWAY Mail: <erik@naggum.uu.no>, <enag@ifi.uio.no> My opinions. Wail: +47-2-836-863 Another int'l standards dude.
mouse@thunder.mcrcim.mcgill.edu (der Mouse) (03/01/91)
In article <483sis-d@massey.ac.nz>, ...!cc-server4.massey.ac.nz!A.J.Rasiah writes: > I am trying to use the out-of-band (OOB) facility of UNIX sockets. I > tried a > send(s, "out of band data", 16, MSG_OOB); /* 1 */ > write(s, "string 2", 8); /* 2 */ You don't say what flavor of UNIX, though with sockets and MSG_OOB it clearly has Berkeley blood in its veins. You also don't say what sort of socket. It's clearly a stream socket, but is it AF_UNIX or AF_INET? I don't know what AF_UNIX does with MSG_OOB. I've neither tried it nor looked at the code. But AF_INET, now, that's a different story. You see, TCP doesn't have out-of-band data. It has an urgent pointer, which marks a point in the data stream, *not* a subsequence of the data stream. Berkeley took this notion and managed to turn it into a sort-of OOB mechanism. But the underlying mechanism is really not suited to sending OOB data, so it's hardly surprising that it breaks. And then various vendors ship code that isn't quite the Berkeley code any longer, so it's broken in subtle ways.... If the sender and receiver use different implementations of TCP, this is even less surprising. The Berkeley code contains a comment that seems to indicate that they violate the TCP spec slightly, in a way that seems to me likely to cause interoperability problems with this pseudo-OOB mechanism, and in fact I've observed problems that I can pretty much justify as being caused by this. If you really want a second data channel, I would recommend creating a second connection. If you want something else, it depends on just what it is you want. der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu