2012-02-06 18 views
0

ioctl()でread()を使用したいが、タイムアウトを使用して読み込み時間を制御したい。 これを行う方法に関するご意見はありますか?私が知っているUnixのC++のソケットでread()を使ってタイムアウトを使用する方法

これまでのところは、次のとおりです。

//CLIENT.cpp 
struct timeval tv={1,0}; 
setsockopt(mysocket, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv)); 
connect(mysocket, &sock_dest, sizeof(struct sockaddr)); 
len = read(mysocket, buffer, 10); 

+1

[fcntl(2)](http://linux.die.net/man/2/fcntl)で 'O_NONBLOCK'を設定してから、[select(2)](http:// linux。 die.net/man/2/select)を使用して、ソケットの読み込み準備が整ったことを確認します(selectではタイムアウトを指定できます)。 –

+0

合意。ところで、 'read'がどれくらい時間がかかるか気にするなら、' connect'がどれくらい時間がかかるか気にする必要があります(タイムアウトすると時間がかかることがあります)。 'connect'を呼び出す前にソケットを非ブロックにすることができ、' select'か 'poll'で両方を扱うことができます。 – Useless

答えて

4

ioctl()はあなたがやりたいことはありません...私は、サーバー上の5秒の遅延を使用してみましたが、それはタイムアウトしませんでした。読み取り時にタイムアウトを使用するには、poll()または古いインターフェイスselect()(私はpoll()を使用します)を使用する必要があります。 SO_RCVTIMEOで設定されたタイムアウトは、新しいデータが受信されるたびにリセットされることがあります。したがって、あなたの例では、それは10秒まで待つことができます。 poll()は、指定されたタイムアウト後にデータがあるかどうかを返します。その場合、非ブロック化read()を使用しているものは何でも読み込むことができます。

+0

私はioctlを使って何バイト読み込めるかを調べていますが、何も準備ができていない場合には、ループをもう一度行いますが、読み込みはブロック呼び出しです。 SELECT呼び出しを置き換えることを目的としています。 – maheshg

+0

'SO_RCTTIMEO'を' timeout/size'の値に設定すると( 'timeout'は秒単位、' size'はバイト単位です)、これにいくらか類似した効果があります。しかし、 'poll()'が利用できない場合は 'poll()'(または 'select()')を使用します。なぜこれらの通話を削除したいですか?彼らはタイムアウトをうまく処理します。 –

+0

同じタイムアウト値を使用している選択呼び出しが多すぎるため、未定義の動作が発生します。このようにして、再試行を実装し、タイムアウトを管理しています。 – maheshg

0

読んでブロックしているのですか、おそらくconnect()でブロックしていますか?私はSO_RCVTIMEO(とSO_SNDTIMEO)オプションがconnect()の動作に影響するとは考えていません。

一般に、非ブロッキングソケット(O_NONBLOCKのfcntl)を使用し、EWOULDBLOCKのerrnoをキャッチして、読み取りセットのソケットと希望のタイムアウトでselect()を実行します。

2

アラームを設定してシステムコールを中断することで、必要な操作を行うことができます。あなたはどこか、メインまたは早期あなたのプログラムのinitプロセスにおけるいくつかの基本的な設定が必要になります。

#include <signal.h> 

sig_atomic_t alarm_counter; 

void alarm_handler(int signal) { 
    alarm_counter++; 
} 

void setup_alarm_handler() { 
    struct sigaction sa; 
    memset(&sa, 0, sizeof(sa)); 
    sa.sa_handler = alarm_handler; 
    sa.flags = 0; 
    if (sigaction(SIGALRM, &sa, 0) < 0) 
     die("Can't establish signal handler"); 
} 
// call setup_alarm_handler in main 

次に、あなたのようにそれを使用することができます:

alarm(10); // set a 10 second timeout 
(len = connect(mysocket, &sock_dest, sizeof(struct sockaddr))) < 0 || 
(len = read(mysocket, buffer, 10)); 
alarm(0); // cancel alarm if it hasn't happened yet 
if (len == -1 && errno == EINTR) 
    // timed out before any data read 
else if (len == -1) 
    // other error 

あなたが呼び出しのシーケンスのタイムアウトを持つことができますこの方法を各コールの所要時間を把握するのではなく、接続または読み取りに時間がかかりすぎるとタイムアウトします。したがって、後続のコールがどれくらい待つかを知ることができます。

関連する問題