How to completely destroy a socket connection in C

93,819

Solution 1

The close call only marks the TCP socket closed. It is not usable by process anymore. But kernel may still hold some resources for a period (TIME_WAIT, 2MLS etc stuff).

Setting of SO_REUSEADDR should remove binding problems.

So be sure that value of true is really non-zero when calling setsockopt (overflow bug may overwrite it):

true = 1;
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int))

There is pid variable is your code. If you use fork (for starting connection handling processs), then you should close sock also in the process which does not need it.

Solution 2

The connection is still active because you forgot to close the connected socket. Closing the listening socket does not automatically close the connected socket.

//necessary code
close(connected);  // <---- add this line
close(sock);
goto label;

I am not sure though why you are getting EADDRINUSE. The code worked fine on both linux and mac os.

Solution 3

First for the naming, so we all name the same things the same:

Server side:

The socket passed to listen() and then to accept() let's call the listening socket. The socket returned by accept() let's call the accepted socket.

Client side:

The socket passed to connect() let's call the connecting/connected socket.


Regarding your issue:

To terminate the accept()ed connection close the accepted socket (what you call connected) by optionally first using shutdown() followed by close ().

To then accept a new connection loop right back before the call to accept(), do not go via bind() and listen() again.

Only shutdown and close the listening socket if you want to get rid of pending connect()s issued after accept() returned.

Share:
93,819
Harikrishnan
Author by

Harikrishnan

Wellversed in: PySpark iOS Application Development Android Application Development Windows UWP Development Electron Angular Hadoop Ecosystem AWS Programming Languages: Java Kotlin Python Javascript Swift Objective-C Love to: Read Travel(I am the one driving/Riding) Movies/Series Code Sleep Interests: Cars Motorcycles Gadgets New Technologies PS : Also loves to keep the above list ever expanding!!!

Updated on December 10, 2020

Comments

  • Harikrishnan
    Harikrishnan over 3 years

    I have made a chat client in linux using socket, and i wish to destroy the connection completely. Following is the relevant portions of the code:

    int sock, connected, bytes_recieved , true = 1, pid;  
    char send_data [1024] , recv_data[1024];     
    struct sockaddr_in server_addr,client_addr;    
    int sin_size;
    label:
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("Socket");
        exit(1);
    }
    if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1)
    {
        perror("Setsockopt");
        exit(1);
    }
    server_addr.sin_family = AF_INET;         
    server_addr.sin_port = htons(3128);     
    server_addr.sin_addr.s_addr = INADDR_ANY; 
    bzero(&(server_addr.sin_zero),8); 
    if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))== -1)
    {
        perror("Unable to bind");
        exit(1);
    }
    if (listen(sock, 5) == -1)
    {
        perror("Listen");
        exit(1);
    }
    printf("\nTCPServer Waiting for client on port 3128");
    fflush(stdout);
    connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);
    //necessary code
    close(sock);
    goto label;
    

    but the close(sock) doesnot seem to close the destroy the connection completely, because after going to 'label' the code is exiting showing the error message

    Unable to bind: Address already in use
    

    That is the connection is not happening again. What can the problem be? Thanks in advance.

    EDIT: What I actually want is, when I run the script from the beginning after destroying the connection, it should run as a fresh program. How can I do it?

    • Mat
      Mat about 12 years
      Why are you doing that? You should loop back to just before the accept, not re-create the server socket.
    • dwalter
      dwalter about 12 years
      Why do you want to close and reopen the listening socket instead of looping around accept() ?
    • n. m.
      n. m. about 12 years
    • Harikrishnan
      Harikrishnan about 12 years
      When I did that, I got the reply You are connected to <ip>, <port> which was the printf i gave to check if the connection is established or not. The connection should be established only if the client runs the program but it is established even without the client running the program on client side. What should I do now?
    • n. m.
      n. m. about 12 years
      "I got the reply You are connected to <ip>, <port>" --- where from? Your code does not contain that. Please show the relevant code.
    • Harikrishnan
      Harikrishnan about 12 years
      printf("\n You are connected to %s , %d)", inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port))‌​; This is placed right below accept().
    • Ciro Santilli OurBigBook.com
      Ciro Santilli OurBigBook.com about 8 years
  • Harikrishnan
    Harikrishnan almost 12 years
    I have tried it but still no luck. The connection is not not getting destroyed.
  • user207421
    user207421 over 4 years
    The shutdown is not necessary before closing. Close implies shutdown unless the SD is shared with another process, which is not the case here. Amd you never need to shutdown the listening socket.
  • user207421
    user207421 over 4 years
    Not necessary before close.
  • alk
    alk over 4 years
    @user207421: Amended my answer accordingly.