# Building a Simple Nonconcurrent TCP Port Scanner in F#

# Building a Simple Nonconcurrent TCP Port Scanner in F#

Port scanning is one of the most fundamental techniques in networking and security. Before diving into high-performance concurrent scanners, it's useful to understand how a basic scanner works by checking **one port at a time**.

In this article, we'll build the foundation of a **nonconcurrent TCP port scanner** using F#.

---

## What Is a Port Scanner?

A port scanner attempts to connect to ports on a target system and determines whether those ports are:

| State | Meaning |
|---------|---------|
| Open | A service is listening and accepts connections |
| Closed | No service is listening |
| Filtered | Traffic is blocked by a firewall or filtering device |

TCP ports range from:

```text
1 - 65535
```

For demonstration purposes, we'll scan only:

```text
1 - 1024
```

These are commonly known as the well-known ports.

---

## Step 1: Generate Target Addresses

Before attempting any network connections, we need a way to generate:

```text
hostname:port
```

combinations.

In F#, a simple loop can accomplish this.

```fsharp
open System

for i in 1 .. 1024 do
    let address = sprintf "scanme.nmap.org:%d" i
    printfn "%s" address
```

Example output:

```text
scanme.nmap.org:1
scanme.nmap.org:2
scanme.nmap.org:3
...
scanme.nmap.org:1024
```

---

## Understanding `sprintf`

The `sprintf` function formats strings similarly to C's `printf`.

```fsharp
let address = sprintf "scanme.nmap.org:%d" i
```

Here:

| Component | Purpose |
|------------|---------|
| `%d` | Integer placeholder |
| `i` | Current port number |
| `sprintf` | Returns a formatted string |

For port `80`, the generated string becomes:

```text
scanme.nmap.org:80
```

---

## Step 2: Attempt a TCP Connection

A TCP scanner determines whether a port is open by trying to establish a connection.

Conceptually:

```text
Connect to target port
    |
    +-- Success -> Open
    |
    +-- Error -> Closed/Filtered
```

In .NET, this is typically done using:

```fsharp
System.Net.Sockets.TcpClient
```

Minimal example:

```fsharp
let client = new System.Net.Sockets.TcpClient()
```

If the connection succeeds, the port is likely open.

---

## Step 3: Always Close Connections

A successful connection consumes operating system resources.

Good network citizenship requires closing connections immediately after testing.

Conceptually:

```fsharp
client.Close()
```

Benefits:

- Releases socket resources
- Prevents connection leaks
- Reduces system overhead
- Mimics professional scanner behavior

---

## Scanner Workflow

The complete nonconcurrent scanning algorithm is straightforward:

```text
for each port
    generate address
    attempt TCP connection

    if success
        print OPEN
        close connection

    else
        continue
```

---

## Why Is It Called Nonconcurrent?

Only one port is tested at a time.

```text
Port 1  -> wait
Port 2  -> wait
Port 3  -> wait
...
Port 1024
```

Advantages:

- Easy to understand
- Easy to debug
- Minimal code complexity

Disadvantages:

- Slow
- Network latency accumulates
- Does not scale to large scans

Modern scanners solve this using:

- Threads
- Async I/O
- Tasks
- Event-driven networking

---

## Educational Value

Even though professional scanners use concurrency, a nonconcurrent scanner teaches several important networking concepts:

- TCP connection establishment
- Socket programming
- Port states
- Error handling
- Resource management
- Network reconnaissance fundamentals

Understanding this sequential model makes it much easier to appreciate how high-performance scanners achieve their speed.

---

## Key Takeaways

- TCP scanners determine port availability by attempting connections.
- A loop can generate target addresses for thousands of ports.
- `sprintf` provides convenient address formatting in F#.
- Successful connections should always be closed.
- Nonconcurrent scanners are simple but relatively slow.
- This approach forms the foundation for advanced concurrent port scanners.

---

A nonconcurrent scanner may not be the fastest tool in a security engineer's toolkit, but it provides an excellent introduction to how network discovery and TCP-based reconnaissance actually work under the hood.
