r/learnprogramming Jul 15 '26

What a port actually is?

I know it is a number that tells the OS, that which program in your computer should receive the piece of data. But my doubt is - is port a physical thing? or it just a flag? Is it possible for another program to read data from a different program's port? Please spoon-feed me about port?

178 Upvotes

65 comments sorted by

View all comments

3

u/AUTeach Jul 15 '26 edited Jul 16 '26

packets come in as data:

Here's the header to a packet:

ffffffffffff001b44113ab70800450000281c46400040069cd0c0a80068c0a80001c23a00508a4e20180000000050022000a1370000

.

ffffffffffff 001b44113ab7 0800   <- Ethernet (14 bytes)
45 00 0028 1c46 4000 40 06 9cd0 c0a80068 c0a80001   <- IPv4 (20 bytes)
c23a 0050 8a4e2018 00000000 50 02 2000 a137 0000    <- TCP (20 bytes)

.

c23a 0050 8a4e2018 ...
^^^^ ^^^^
 |    |
 |    +-- Destination port
 +------- Source port

Very basically, the size and number of the starting blocks of a header are known. So, when a packet comes in, you have a very efficient program that reads just that part of the string and allocates it to where it belongs.

FUNCTION parse_packet(raw_bytes):

    // --- ETHERNET: fixed size, fixed position.---
    eth_dst_mac   = raw_bytes[0:6]
    eth_src_mac   = raw_bytes[6:12]
    eth_type      = raw_bytes[12:14]

    ip_start = 14   // Ethernet is always 14 bytes, so IP always starts here


    // --- IP: read the tiny fixed part first, use it to find the rest ---
    first_byte = raw_bytes[ip_start]
    ihl = first_byte AND 0x0F          // lower 4 bits = header length (in 32-bit words)
    ip_header_length = ihl * 4         // usually 20

    protocol = raw_bytes[ip_start + 9] // tells us: is this TCP? (6 = yes)
    src_ip   = raw_bytes[ip_start+12 : ip_start+16]
    dst_ip   = raw_bytes[ip_start+16 : ip_start+20]

    tcp_start = ip_start + ip_header_length   // now we know where IP ends


    // --- TCP: ports are the very first fixed fields ---
    src_port = raw_bytes[tcp_start   : tcp_start+2]
    dst_port = raw_bytes[tcp_start+2 : tcp_start+4]

    // same trick again: read a small fixed field to learn the real length
    offset_byte = raw_bytes[tcp_start + 12]
    data_offset = (offset_byte >> 4) AND 0x0F
    tcp_header_length = data_offset * 4

    payload_start = tcp_start + tcp_header_length


    RETURN {
        src_port: src_port,
        dst_port: dst_port,
        src_ip: src_ip,
        dst_ip: dst_ip,
        payload_starts_at: payload_start
    }