How to make TCP server in Odin lang

Dhadve YashDhadve Yash
2 min read

Basic tcp server

package main

import "core:fmt"
import "core:net"
import "core:strings"
import "core:bytes"

main :: proc (){
    // setting up socket for our server
    listen_socket, listen_err := net.listen_tcp(net.Endpoint{
        port = 8000,
        address = net.IP4_Loopback
    })
    if listen_err != nil {
        fmt.panicf("listen error : %s", listen_err)
    }

    // setting up socket for the client to connect to
    client_socket, client_endpoint, accept_err := net.accept_tcp(listen_socket)

    if accept_err != nil {
        fmt.panicf("%s",accept_err)
    }

    handleClient(client_socket)
}

handleClient ::proc(client_soc :net.TCP_Socket) {
    // This loops till our client wants to disconnect
    for {
        // allocating memory for our data
        data_in_bytes :[8]byte
        // receving some data from client
        _ ,err := net.recv_tcp(client_soc, data_in_bytes[:])
        if err != nil {
            fmt.panicf("error while recieving data %s", err)
        }
        // this is just "exit" in byte format
        exit_code := [8]byte{101, 120, 105, 116, 13, 10, 0, 0}
        if data_in_bytes == exit_code{
            fmt.println("connection ended")
            break
        }
        // converting bytes data to string
        data, e := strings.clone_from_bytes(data_in_bytes[:], context.allocator)
        fmt.println("client said :",data)
    }
}

MultiThreaded tcp server

package main

import "core:bytes"
import "core:fmt"
import "core:mem/virtual"
import "core:net"
import "core:mem"
import "core:strings"
import "core:sync"
import "core:thread"

clientData :: struct {
    client_socket: net.TCP_Socket,
    waitgroupdata: ^sync.Wait_Group,
}
main :: proc() {

    default_allocator := context.allocator
    tracking_allocator :mem.Tracking_Allocator
    mem.tracking_allocator_init(&tracking_allocator, default_allocator)
    context.allocator =  mem.tracking_allocator(&tracking_allocator) 
    reset_tracking_allocator :: proc (a :^mem.Tracking_Allocator)  -> bool {
        err := false

        for _, val in a.allocation_map {
            fmt.printf("%v leaked:%v bytes \n", val.location, val.size)
            err := true
        }
        mem.tracking_allocator_clear(a)
        return err
    }
    defer reset_tracking_allocator(&tracking_allocator)

    wg: sync.Wait_Group
    threadPool := make([dynamic]^thread.Thread, 0, 20)
    defer delete(threadPool)

    // setting up socket for our server
    listen_socket, listen_err := net.listen_tcp(
        net.Endpoint{port = 8000, address = net.IP4_Loopback},
    )
    if listen_err != nil {
        fmt.panicf("listen error : %s", listen_err)
    }

    // setting up socket for the client to connect to

    for {
        sync.wait_group_add(&wg,1)
        client_soc, client_endpoint, accept_err := net.accept_tcp(listen_socket)
        if accept_err != nil {
            fmt.panicf("%s", accept_err)
        }
        thr := thread.create(handleClient)
        thr.data = &clientData{
            client_socket = client_soc,
            waitgroupdata = &wg
        }
        append(&threadPool, thr)
        thread.start(thr)
    }
    sync.wait_group_wait(&wg)

    fmt.println("Program Ended")
}

handleClient :: proc(t: ^thread.Thread) {
    client_data := (cast(^clientData)t.data)
    for {
        // allocating memory for our data
        data_in_bytes: [8]byte
        // receving some data from client
        _, err := net.recv_tcp(client_data.client_socket, data_in_bytes[:])
        if err != nil {
            fmt.panicf("error while recieving data %s", err)
        }
        // this is just "exit" in byte format
        exit_code := [8]byte{101, 120, 105, 116, 13, 10, 0, 0}
        if data_in_bytes == exit_code {
            fmt.println("connection ended with a client")
            break
        }
        o := cast ([]u8){'s','e','n','t', '\n'}
        net.send_tcp(client_data.client_socket, o)
        // converting bytes data to string
        data, e := strings.clone_from_bytes(data_in_bytes[:], context.allocator)
        fmt.println("client said :", data)
    }

    net.send_tcp(client_data.client_socket, []byte{121, 111, 117, 32, 99, 97, 110, 32, 101, 120, 105, 116, 32, 110, 111, 119, 13, 10})
    sync.wait_group_done(client_data.waitgroupdata)
    thread.destroy(t)
}
0
Subscribe to my newsletter

Read articles from Dhadve Yash directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dhadve Yash
Dhadve Yash