In my client code, I am following these steps to connect to a socket:
Creating a socket
sockDesc = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
Connecting it (retry for 'x' time in case of failure)
connect(sockDesc, (sockaddr *) &destAddr, sizeof(destAddr))
(After filling the
destAddr
fields)Using the socket for
send()
/recv()
operation:send(sockDesc, buffer, bufferLen, 0) recv(sockDesc, buffer, bufferLen, 0)
close()
the socket descriptor and exitclose(sockDesc)
If during send()
/recv()
the connection breaks, I found that I could connect by returning to step 2.
Is this solution okay? should I close the socket descriptor and return to step 1?
Another interesting observation that I am not able to understand is when
I stop my echo server and start the client. I create a Socket (step 1) and call connect()
which fails (as expected) but then I keep calling connect()
, lets say, 10 times. After 5 retries I start the server and connect()
is successful. But during the send()
call it receives SIGPIPE
error. I would like to know:
1) Do I need to create a new socket every time connect()
fails? As per my understanding as long as I have n开发者_JAVA百科ot performed any send()
/recv()
on the socket it is as good as new and I can reuse the same fd
for the connect()
call.
2) I don't understand why SIGPIPE
is received when the server is up and connect()
is successful.
Yes, you should close and go back to step 1:
close() closes a file descriptor, so that it no longer refers to any file and may be reused.
From here.
I think closing the socket is the right thing to do, despite the fact that it may work if you don't.
A socket which has failed to connect may not be in EXACTLY the same state as a brand new one - which could cause problems later. I'd rather avoid the possibility and just make a new one. It's cleaner.
TCP sockets hold a LOT of state, some of which is implementation-specific and worked out from the network.
Sockets corresponding to broken connection is in unstable state. normally you will not be allowed to connect to again unless the operating system release the socket.
I think it will be better to close() and connect again.. you don't have to create another socket.
Anyway, make sure to set LINGER of your socket to ensure that no data is lost in transmision.
See http://www.gnu.org/s/libc/manual/html_node/Socket_002dLevel-Options.html#Socket_002dLevel-Options
If the connection was broken and you try to write on the file descriptor you should get the broken pipe error/signal. All this is saying is that the file descriptor you tried writing to no longer has anyone on the other side to read what you are sending.
What you can do is catch the signal SIGPIPE and then deal with the reconnecting by closing the FD and going back to your step 1. You will now have a new FD you can read and write from for the connection.
If the Single UNIX Specification doesn't say that it MUST work to go back to step #2 instead of step #1, then the fact that it happens to work on Linux is just an implementation detail, and you would be far better off and more portable if you go back to step #1. As far as I am aware, the specification does not make any guarantee that it is ok to go back to step #2 and, therefore, I would advise you to go back to step #1.
精彩评论