2011-06-26 5 views
1

私はローカルIPC用のライブラリを作成しています。これはサーバとクライアントの両方で動作するはずです。サーバが準備ができていなければ、失敗して再試行するという戦略です。サーバーが準備ができていないときに接続に失敗する方法はありますか?

このテストでは、サーバーとクライアントの両方として通信する2つのプロセスを作成しました。

しかし、サーバーがビジー状態のときにクライアントコードが失敗しないため、現在の実装に問題があります。

問題が最高のstraceからの抜粋で示されている:

execve("./RemoteSubjects", ["./RemoteSubjects"], [/* 72 vars */]) = 0 

// Client A starts 
28069  .000105 socket(PF_FILE, SOCK_STREAM, 0) = 3 
28069  .000031 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) 
28069  .000006 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 
28069  .000047 unlink("/tmp/A.ipc") = 0 
28069  .000007 bind(3, {sa_family=AF_FILE, path="/tmp/A.ipc"}, 110) = 0 
28069  .000007 listen(3, 0) = 0 

// Client B starts 
28070  .000031 socket(PF_FILE, SOCK_STREAM, 0) = 3 
28070  .000012 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) 
28070  .000005 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 
28070  .000030 unlink("/tmp/B.ipc") = 0 
28070  .000034 bind(3, {sa_family=AF_FILE, path="/tmp/B.ipc"}, 110) = 0 
28070  .000027 listen(3, 0)  = 0 

// Client A creates a socket, which it intend to use for communication with B 
28069  .000023 socket(PF_FILE, SOCK_STREAM, 0) = 4 
28069  .000016 fcntl(4, F_GETFL) = 0x2 (flags O_RDWR) 
28069  .000024 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0 

// Client B creates a socket, which it intend to use for communication with A 
28070  .000038 socket(PF_FILE, SOCK_STREAM, 0) = 4 
28070  .000016 fcntl(4, F_GETFL <unfinished ...> 

// Client A connects to B 
28069  .000004 connect(4, {sa_family=AF_FILE, path="/tmp/B.ipc"}, 110 <unfinished ...> 

// Client B creates a socket, which it intend to use for communication with A 
28070  .000011 <... fcntl resumed>) = 0x2 (flags O_RDWR) 
28070  .000007 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0 

// Client B connects to A 
28070  .000015 connect(4, {sa_family=AF_FILE, path="/tmp/A.ipc"}, 110 <unfinished ...> 

// Client A's connect returned 
28069  .000010 <... connect resumed>) = 0 

// Here is what I do not understand... Why does connect returns 0 when the backlog 
// is set to 0 and B has not accepted? 

何が起こるしたいと思い、私は世論調査は上の活動を報告するのを待つのイベントループ内のサーバーをキャッチするまでの接続が失敗したということですファイル記述子3.私は適切にタイムアウト(SO_RCVTIMEO/SO_SNDTIMEO私は思う)を設定する必要があります。

しかし、これを解決するにはどうすればよいですか?また、受け入れが呼び出されない場合は接続が失敗することを確認してください。

答えて

2

listen()を呼び出すと、着信接続を許可する意思が示され、受け入れキューが作成されます。カーネルは、受け入れキューに新しい接続を置いて、バックグラウンドで接続の確立を管理します。 accept()関数は、次の完全に完了した接続を受け入れキューから取り除き、何も送信させません。 バックログ引数として

POSIX states that this is a hint

バックログ引数は、実装がソケットの聞くキューに未処理の接続の数を制限するために使用しなければならない実装にヒントを提供します。

また言う:0の

バックログ引数がソケットが接続を受け入れることを可能にするその場合にリッスンキューの長さは、実装定義された最小値に設定されてもよいです。

あなたはconnect()が失敗する場合は、それが成功するために準備が整うまで、listen()を呼び出すことはありません。 accept()にコールした後、接続が成功しないようにする場合は、リスニングソケットを閉じます(受け入れキューにある追加の接続はすべて中止されます)。または、接続を受け入れると、アプリケーションがソケットを介して何らかのデータを送信するようにします(まだそうしていない場合)。特定のタイムアウト期間内に相手側が何も受信しない場合、接続を閉じることができます。

関連する問題