views:

198

answers:

1

Short Question
What's the right way to handle a Ctrl-C event sent over Telnet on the server side?

Long Question
After calling recv() on a socket, I'd like to handle some situations appropriately. One of them is to return a certain error code when Ctrl-C was received. What's the correct way to detect this? The following works, but it just doesn't seem right:

size_t recv_count;
static char ctrl_c[5] = {0xff, 0xf4, 0xff, 0xfd, 0x06};

recv_count = recv(socket, buffer, buffer_size, 0);

if (recv_count == sizeof(ctrl_c) &&
    memcmp(buffer, ctrl_c, sizeof(ctrl_c) == 0)
{
    return CTRL_C_RECEIVED;
}

I found a comment on Ctrl-C in a side-note in this UNIX Socket FAQ:

[...] (by the way, out-of-band is often used for that ctrl-C, too).

As I understand, receiving out-of-band data is done using recv() with a certain flag as the last parameter. But when I'm waiting for data using recv() as I do in the code above, I can't read out-of-band data at the same time. Apart from that, I'm getting something using recv() without that oob-flag.

A: 

Set the socket to non-blocking with fcntl(), use select() (pselect() on some systems) to check for arriving data. That is how to sample a socket's current condition, i.e. whether it has data to recv() and if can accept a send(), or there is an exception. Don't simply sit there blocking.

A recv() returns as much available information as the size of the buffer supplied can hold. If the socket has been configured to receive of out-of-band data (socket option SO_OOBINLINE) and there is unread OOB data, only out-of-band data is returned. Call ioctl() SIOCATMARK to determine whether any more out-of-band data remains un-read.

When you receive OOB data you cannot recv() past the end of the OOB packet in a single recv() call, so it is goof-proof in that regard.

I don't know what is considered best practice, but the idea of grabbing ctrl-c ahead of other already buffered socket data is a good one.

jim mcnamara
Actually, I'm writing a library for in-house use that offers convenience functions for sockets (there's already some fcntl() and select() in there), so this problem isn't specific to a concrete app's implementation, but rather "just another thing my cool library can help with". I was hoping to catch events such as a ctrl-c without OOB data to keep it simple. I agree about not just sitting around in recv() and wait and my library supports blocking and non-blocking modes, but it would have been nice to implement this stuff once and it works every time (tm).Anyway, thanks for the answer!
ogott
http://linux.softpedia.com/get/Programming/Libraries/sWrapper-35278.shtml
jim mcnamara
The above link is an example of some similar efforts to make sockets less involved. IMO the more involved approach lets you 'tweak the settings' to your exact needs. 'exact needs' might be hard to do without adding a lot of complex options in your code.Which undoes the intent of your effort, somewhat.
jim mcnamara
I just took a look at the swrapper code and I think it doesn't really do that much, especially nothing related to my original question. I already wrote a lot of convenience functions we need for our apps (getting/setting timeouts, buffer sizes, linger status, blocking status, ...) and not having this Ctrl-C detection isn't too bad, it just would have been nice. Thanks anyways!
ogott