2010-06-10 56 views
5

Short Question
在服務器端通過Telnet發送Ctrl-C事件的正確方法是什麼?POSIX套接字:如何檢測通過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; 
} 

我發現一個側面說明上按Ctrl-C評論中this Unix套接字FAQ:

[...] (順便說一下,out-of-band通常也用於該ctrl-C)。

據我所知,使用帶有特定標誌的recv()作爲最後一個參數來接收帶外數據。但是,當我像使用上面的代碼一樣使用recv()等待數據時,我無法同時讀取帶外數據。除此之外,我得到東西使用recv()沒有那個oob標誌。

+0

通過telnet發送Ctrl-D作爲^ D(0x04)字符 – 2016-04-21 12:56:57

回答

2

使用fcntl()將套接字設置爲非阻塞,在某些系統上使用select()(pselect())來檢查是否到達數據。這就是如何對套接字的當前條件進行採樣,即它是否具有要recv()的數據並且是否可以接受send(),或者是否存在異常。不要簡單地坐在那裏阻止。

recv()會返回儘可能多的可用信息,因爲所提供的緩衝區的大小可以保持不變。如果套接字已配置爲接收帶外數據(套接字選項SO_OOBINLINE)並且存在未讀的OOB數據,則僅返回帶外數據。調用ioctl()SIOCATMARK以確定是否有更多的帶外數據保持未讀取。

當您收到OOB數據時,您無法在單個recv()調用中recv()超過OOB數據包的末尾,因此在這方面是無法證明的。

我不知道什麼是最佳實踐,但在其他已經緩衝的套接字數據之前抓取ctrl-c的想法是一個好主意。

+0

實際上,我正在編寫一個內部使用的庫,它爲套接字提供了便利函數(這裏已經有一些fcntl()和select() ),所以這個問題並不是特定於具體應用程序的實現,而是「我的酷圖書館可以幫助的另一件事」。我希望能夠捕捉諸如沒有OOB數據的ctrl-c等事件,以保持簡單。 我同意不只是圍坐在recv()等待,我的圖書館支持阻塞和非阻塞模式,但它會很好地實現這個東西一次,它每次都工作(tm)。 無論如何,謝謝你的回答! – 2010-06-10 14:10:00

+0

http://linux.softpedia.com/get/Programming/Libraries/sWrapper-35278.shtml – 2010-06-10 18:44:09

+0

上面的鏈接是一些類似的努力使插座更少涉及的一個例子。國際海事組織更多參與的方法可以讓您根據您的確切需求調整設置。如果不在代碼中添加許多複雜選項,「確切需求」可能很難做到。 這有點解除了你努力的目的。 – 2010-06-10 18:46:49