How to make TCP server in Odin lang
Dhadve Yash
2 min read
Table of contents
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