Solving Port 9999 Stuck in TIME_WAIT State After Process Termination in Ubuntu

On Ubuntu systems, when a process occupies port 9999 and the port remains unavailable due to TIME_WAIT state after the process terminates, preventing new processes from binding to it, you can implement several solutions:

Solution 1: Implement SO_REUSEADDR Socket Option

Configure your application code with the SO_REUSEADDR option to permit immediate reuse of ports in TIME_WAIT condition. This approach works across various network programming environments.

Node.js Implementation

const http = require('http');

const app = http.createServer((req, res) => {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Server running on port 9999\n');
});

app.listen({
  port: 9999,
  host: '0.0.0.0',
  reuseAddr: true  // Enable address reuse
}, () => {
  console.log('Application listening on port 9999');
});

Python Socket Configuration

import socket
import time

def create_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # Enable address reuse
    server_socket.bind(('0.0.0.0', 9999))
    server_socket.listen(10)
    
    print("Server initialized on port 9999")
    
    try:
        while True:
            client_connection, client_address = server_socket.accept()
            print(f"Incoming connection from {client_address}")
            client_connection.close()
    except KeyboardInterrupt:
        print("Shutting down server...")
    finally:
        server_socket.close()

if __name__ == "__main__":
    create_server()

This approach prevents the TIME_WAIT port blocking issue effectively.

Solution 2: Manual Port Release Procedures

When ports remain occupied, execute these manual release steps:

  1. Identify the occupying process
sudo lsof -i :9999

Alternatively:

sudo ss -tulnp | grep 9999

  1. Forcefully terminate the process
sudo kill -9 <PROCESS_ID>

Replace <PROCESS_ID> with the actual process identifier.

  1. Check TIME_WAIT status
ss -tan | grep 9999

  1. Force termination of TIME_WAIT connections
sudo fuser -k 9999/tcp

Solution 3: Linux Kernel Parameter Optimization

To globally minimize the duration ports remain in TIME_WAIT state, adjust kernel parameters:

  1. Reduce TIME_WAIT retention period
sudo sysctl -w net.ipv4.tcp_fin_timeout=8

The default value is 60 seconds before releasing TIME_WAIT connections.

  1. Enable rapid reuse of TIME_WAIT ports
sudo sysctl -w net.ipv4.tcp_tw_reuse=1

⚠️ Note: tcp_tw_recycle has been deprecated since Linux 4.12. Use tcp_tw_reuse=1 for newer systems.

  1. Make changes persistent
    Add parameters to /etc/sysctl.conf:
echo "net.ipv4.tcp_fin_timeout=8" | sudo tee -a /etc/sysctl.conf
echo "net.ipv4.tcp_tw_reuse=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Solution 4: Utilize SO_LINGER for Immediate Port Release

In low-level programming environments like C/C++, employ the SO_LINGER option to immediately release ports upon process closure:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>

int main() {
    int socket_descriptor = socket(AF_INET, SOCK_STREAM, 0);
    
    struct linger linger_options;
    linger_options.l_onoff = 1;   // Enable linger
    linger_options.l_linger = 0;  // Linger time = 0
    setsockopt(socket_descriptor, SOL_SOCKET, SO_LINGER, &linger_options, sizeof(linger_options));

    struct sockaddr_in server_address;
    memset(&server_address, 0, sizeof(server_address));
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(9999);
    server_address.sin_addr.s_addr = INADDR_ANY;

    bind(socket_descriptor, (struct sockaddr*)&server_address, sizeof(server_address));
    listen(socket_descriptor, 5);

    printf("Server active on port 9999...\n");
    
    while (1) {
        int client_socket = accept(socket_descriptor, NULL, NULL);
        if (client_socket > 0) {
            printf("Connection received\n");
            close(client_socket);
        }
    }

    close(socket_descriptor);
    return 0;
}

This SO_LINGER configuration immediately releases the port upon close() execution, bypassing the TIME_WAIT state entirely.

Solution Comparison Matrix

Solution Method Applicable Scenarios Recommendation Level
Implemetn SO_REUSEADDR Modifiable codebase, TIME_WAIT prevention ✅ Recommended
Manual Port Release Temporary resolution of occupancy issues ⚠️ Requires manual intervention
Kernel Parameter Adjustment Affects global TCP port release behavior ⚠️ Impacts entire system
Use SO_LINGER Low-level C/C++ programming environments ✅ Recommended (C/C++ specific)

Optimal Implementation Strategy

  • Code-level approach: Implement SO_REUSEADDR
  • System optimization: Adjust tcp_fin_timeout
  • Emergency procedures: Manual release (fuser -k 9999/tcp)

These approaches eliminate the problem of ports remaining locked in TIME_WAIT state for extended periods.

Tags: Linux networking Sockets Ubuntu tcp

Posted on Mon, 01 Jun 2026 18:10:43 +0000 by gibbo1715