Adil
Adil

Reputation: 2538

Reusing socket descriptor on connection failure

In my client code, I am following these steps to connect to a socket:

  1. Creating a socket

    sockDesc = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)  
    
  2. Connecting it (retry for 'x' time in case of failure)

    connect(sockDesc, (sockaddr *) &destAddr, sizeof(destAddr))  
    

    (After filling the destAddr fields)

  3. Using the socket for send()/recv() operation:

    send(sockDesc, buffer, bufferLen, 0)  
    recv(sockDesc, buffer, bufferLen, 0)  
    
  4. close() the socket descriptor and exit

    close(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 not 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.

Upvotes: 13

Views: 15933

Answers (5)

MarkR
MarkR

Reputation: 63538

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.

Upvotes: 5

Michael Aaron Safyan
Michael Aaron Safyan

Reputation: 95489

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.

Upvotes: 2

Chris
Chris

Reputation: 815

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.

Upvotes: 3

Yousf
Yousf

Reputation: 3997

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

Upvotes: 4

Hassan Syed
Hassan Syed

Reputation: 20485

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.

Upvotes: 7

Related Questions