开发者

How to make connect fail when the server is not ready?

I am writing a library for local IPC, which should act both as server and client. The strategy is to fail and try again if the server is not ready.

For this test I have create two process which are communicating both as server and client.

But I have have a problem with my current implementation, because the client code does not fail when the server are busy.

The problem is best illustrated with a snippet from 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开发者_如何学Go|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?

What I would like to happen is that the connect should fail until I catch the server in its event loop waiting for poll to report activity on file descriptor 3. I should properly set a timeout (SO_RCVTIMEO/SO_SNDTIMEO i think) allowing connect to block for 10ms to increase changes for the server to accept the connect.

But how should I fix this, and make sure connect fails if accept is not called?


By calling listen(), you indicate your willingness to allow incoming connections, and an accept queue is created. The kernel takes care of connection establishment behind the scenes, putting new connections on the accept queue. The accept() function just takes the next fully completed connection off the accept queue and does not cause anything to be sent.

As for the backlog argument, POSIX states that this is a hint:

The backlog argument provides a hint to the implementation which the implementation shall use to limit the number of outstanding connections in the socket's listen queue.

It also says:

A backlog argument of 0 may allow the socket to accept connections, in which case the length of the listen queue may be set to an implementation-defined minimum value.

If you want the connect() to fail, do not call listen() until you are ready for it to succeed. And after calling accept(), close the listening socket if you don't want any more connections to succeed (any additional connections sitting in the accept queue will be aborted). Alternatively, have the application send some data over the socket once it accepts the connection (if it doesn't already do so); if the other side does not receive anything within a certain timeout period it could close the connection.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜