tags:

views:

330

answers:

5

In my client code (Linux), 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 oepration:

    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 was broken, I found that I could connect by returning to step 2.

Is this solution okay? ...or should I close the socket descriptor and return to step 1?

Another interesting thing observed which i am not able to understand. I stop my echo server and start the client. Socket is created (step 1) and connect fails (as expected) but the connect call is retried lets say 10 times. After 5 retries i have started the server and connect is successful. But during send() call it recives SIGPIPE error. I would like to know:-

1) Here also I need to create new Socket after each connect() call failure? As per my understanding as i have not issued any send/recv call on the socket it is as good as newly created socket so i can reuse the same fd for connect() call

2) I dont understand why SIGPIPE is received when the server is up and connect is successful.

+2  A: 

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.

Hassan Syed
Any specific reason? As I am using the same fd in the connect call to reconnect with the server and not creating any new socket, it should not harm? or in this case socket goes into wait state or something?
Adil
Well the specifications suggest that the "file" no longer refers to anything. To me this indicates that the handle is still valid however it needs to be re-initialized.
Hassan Syed
+3  A: 

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

Yousf
If i close the descriptor, i think i need to create the socket again because closing the descriptor means destroying the socket, right?
Adil
+1  A: 

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.

Chris
+1  A: 

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.

Michael Aaron Safyan
+2  A: 

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.

MarkR