3

I developed an application which contains a small http server.

my application is launched in the boot. if the application is stopped normally (etc/init.d/myappli stop) the socket will be closed

close (socket_desc); 

but if I kill it with kill -9 the socket will not be closed

http server code :

void http_server_init(void)
{
    struct sockaddr_in server;
    int cr_port;

    for(;;) {
        cr_port = conf.port;
        int i = (DEFAULT_PORT == cr_port)? 1 : 0;
        //Create socket
        cr_socket_desc = socket(AF_INET , SOCK_STREAM , 0);
        if (cr_socket_desc == -1)
        {
            LOG (ERROR,"Could not open server socket, Error no is : %d, Error description is : %s", errno, strerror(errno));
            sleep(1);
            continue;
        }

        /* enable SO_REUSEADDR */
        int reusaddr = 1;
        if (setsockopt(cr_socket_desc, SOL_SOCKET, SO_REUSEADDR, &reusaddr, sizeof(int)) < 0) {
            LOG (WARNING,"setsockopt(SO_REUSEADDR) failed");
        }

        //Prepare the sockaddr_in structure
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = INADDR_ANY;
        for(;;i++) {
            server.sin_port = htons(cr_port);
            //Bind
            if( bind(cr_socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
            {
                //print the error message
                LOG (ERROR,"Could not bind server socket on the port %d, Error no is : %d, Error description is : %s", cr_port, errno, strerror(errno));
                cr_port = DEFAULT_PORT + i;
                LOG (INFO,"Trying to use another port: %d", cr_port);
                continue;
            }
            break;
        }
        break;
    }
    LOG (INFO,"server initiated with the port: %d", cr_port);
}

Questions:

1) How to close socket if the program was killed?

2)And what is the type of socket should be used in this case to avoid that the socket will not be used by another process using tcp socket?

Anis_Stack
  • 3,306
  • 4
  • 30
  • 53
  • 2
    All file descriptors will be closed by the OS when your process exits, so no need to worry. – Crowman Feb 02 '15 at 15:17
  • 2
    Since SIGKILL (-9) couldn't be handled, `close()` should be done automatically by OS. Do you have problems with that? – myaut Feb 02 '15 at 15:17
  • What observation makes you think "the socket will not be closed"? – Jens Feb 02 '15 at 15:31
  • because the port is taken by another process !!!! – Anis_Stack Feb 02 '15 at 15:34
  • I use openwrt system – Anis_Stack Feb 02 '15 at 15:37
  • @Anis_Stack And how do you think your program can prevent "another process from taking the port"? – Jens Feb 02 '15 at 15:39
  • 1
    If you're shutting the process down and immediately trying to start it up again, the connection is probably just sitting in the `TIME_WAIT` state for a while, which is normal. – Crowman Feb 02 '15 at 15:39
  • TIME_WAIT status doesn't make a problem because I use the reuse option ' SO_REUSEADDR' – Anis_Stack Feb 02 '15 at 15:40
  • `SO_REUSEADDR` doesn't do what you think. read the accepted answer for this question: http://stackoverflow.com/questions/14388706/socket-options-so-reuseaddr-and-so-reuseport-how-do-they-differ-do-they-mean-t – Klas Lindbäck Feb 02 '15 at 16:22
  • possible duplicate of [My linux application port is taken by another service when it's stopped](http://stackoverflow.com/questions/28237517/my-linux-application-port-is-taken-by-another-service-when-its-stopped) – Crowman Feb 02 '15 at 23:59

2 Answers2

8

If you kill a program with kill -9 the port will be closed, not by the program, but by the operating system. The fact it is being closed is precisely what is making it available for being taken over by another process.

Ports are not 'reserved' for particular programs. The only reservation of ports after the death of the program is if you don't set SO_REUSEADDR in which case it's reserved for (from memory) 2 TIME_WAIT periods. But you've told us in the comments you do set SO_REUSEADDR. What that means is 'make the port available to the next program that tries to listen on it'. It doesn't differentiate between that program being the same program or a different one.

I think you think that SO_REUSEADDR means 'this program may want to reuse the port so don't give it to anyone else'. That is categorically not what SO_REUSEADDR does. SO_REUSEADDR (broadly speaking, and on Unix anyway) releases the port for use by any program to the operating system immediately after your program dies, as opposed to waiting for a while. On MS it is (somewhat bizarrely) used to bind to a port that's already in use. For more information, see Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems? - however note that on no operating system does it mean what I'm guessing you think it means.

Community
  • 1
  • 1
abligh
  • 24,573
  • 4
  • 47
  • 84
  • 1
    AKA 'don't use two servers on the same listening port'. Kinda obvious, really:) – Martin James Feb 02 '15 at 16:11
  • It's really strange, how can another service take the port of the socket of my program if it was stopped by kill -9 – Anis_Stack Feb 02 '15 at 16:33
  • What's so strange about another service doing this when your process is terminated? What would be strange is if it did that when your process was running. – Crowman Feb 02 '15 at 16:52
  • @Anis_Stack your program is stopped. It no longer uses the port. Therefore another program can use it. It's as simple as that. I've added another paragraph to explain. – abligh Feb 02 '15 at 19:18
1

Your problem is that the old socket will be in TIME_WAIT state a short while before it is released. If you want to reduce the time spent in the TIME_WAIT state you can reduce the linger time. Note that there are risks attached to reducing it too much.

You can change the linger time for your socket using setsockopt(2).

Related links:

The ultimate SO_LINGER page

TCP option SO_LINGER (zero)

Community
  • 1
  • 1
Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82
  • I don't think that can be right. OP told us in the comments he set `SO_REUSEADDR` which means it should be reusable immediately. Moreover, he appears not to be complaining that the socket *can't* be reused; rather he's complaining that it *can* be reused (by other programs). So his problem can't be that the socket is stuck in `TIME_WAIT`. I agree you've answered the most common question on this subject well, but apparently not this question. – abligh Feb 02 '15 at 19:21
  • To be fair though, it's not at all clear from the question or the comments how the OP knows that the socket is being reused by a different program rather than the same program, or whether he/she is right about that. Having another process lurking and jumping in to steal it exactly in the time between killing his process and restarting it does seem a little unlikely, to me. The question is poorly worded, and doesn't actually ask at all for an explanation of the hinted-at but undescribed behavior - just "how to close socket if the program was killed?" – Crowman Feb 02 '15 at 19:39