POSIX套接字:如何检测通过Telnet发送的Ctrl-C?

POSIX套接字:如何检测通过Telnet发送的Ctrl-C?,c,sockets,terminal,telnet,copy-paste,C,Sockets,Terminal,Telnet,Copy Paste,简短问题 处理通过Telnet在服务器端发送的Ctrl-C事件的正确方法是什么 长问题 在套接字上调用recv()之后,我想适当地处理一些情况。其中之一是在收到Ctrl-C时返回某个错误代码。正确的检测方法是什么?以下方法可行,但似乎并不正确: size_t recv_count; static char ctrl_c[5] = {0xff, 0xf4, 0xff, 0xfd, 0x06}; recv_count = recv(socket, buffer, buffer_size, 0);

简短问题
处理通过Telnet在服务器端发送的Ctrl-C事件的正确方法是什么

长问题
在套接字上调用recv()之后,我想适当地处理一些情况。其中之一是在收到Ctrl-C时返回某个错误代码。正确的检测方法是什么?以下方法可行,但似乎并不正确:

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;
}
我在UNIX Socket常见问题解答的旁注中找到了关于Ctrl-C的注释:

[…](顺便说一句,带外也经常用于ctrl-C)


据我所知,接收带外数据是使用recv()完成的,最后一个参数是某个标志。但是当我像在上面的代码中那样使用recv()等待数据时,我不能同时读取带外数据。除此之外,我还使用recv()获得了一些东西,但没有oob标志。

使用fcntl()将套接字设置为非阻塞,使用select()(在某些系统上使用pselect()检查到达的数据。这就是如何对套接字的当前状态进行采样,即它是否有要recv()的数据,是否可以接受send(),或者是否存在异常。不要只是坐在那里阻拦

recv()返回提供的缓冲区大小所能容纳的可用信息。如果套接字已配置为接收带外数据(套接字选项SO_OOBINLINE),并且存在未读的OOB数据,则只返回带外数据。调用ioctl()SIOCATMARK以确定是否还有更多带外数据保持未读取状态

当您收到OOB数据时,您无法在单个recv()调用中将其recv()超过OOB数据包的结尾,因此这是一个很好的证明


我不知道什么是最佳实践,但是在其他已经缓冲的套接字数据之前获取ctrl-c是一个好主意

事实上,我正在编写一个内部使用的库,它为套接字提供了方便的函数(其中已经有一些fcntl()和select()),因此这个问题并不是具体应用程序的实现所特有的,而是“我的酷库可以帮到的另一件事”。我希望捕捉到一些事件,比如没有OOB数据的ctrl-c,以保持简单。我同意不只是坐在recv()中等待,而且我的库支持阻塞和非阻塞模式,但如果只实现一次这种东西就好了,而且每次都可以使用(tm)。无论如何,谢谢你的回答!上面的链接是一些类似的努力的一个例子,以减少套接字的参与。在我看来,更复杂的方法可以让你根据自己的具体需要“调整设置”如果不在代码中添加大量复杂选项,可能很难做到“精确需求”。我只是看了一下swrapper代码,我认为它并没有起到多大作用,尤其是与我最初的问题无关。我已经为我们的应用程序编写了很多方便的函数(获取/设置超时、缓冲区大小、延迟状态、阻塞状态等等),没有这种Ctrl-C检测也不太糟糕,这会很好。无论如何谢谢你@jimmcnamara关于该语句,“如果套接字已配置为接收带外数据(套接字选项SO_OOBINLINE),并且存在未读的OOB数据,则只返回带外数据。”这听起来与SO_OOBINLINE的语义完全相反(但听起来确实像是将MSG_OOB与recv()一起使用)。我一点也不确定这是否正确;再说一遍,我也不确定这是不是错的。您能提供一个参考吗?Ctrl-D由telnet以^D(0x04)字符发送