From f65a9a5e21860f179859b0be75f7bb30a0253b65 Mon Sep 17 00:00:00 2001 From: owenw2 <owenw2@sp25-cs425-0601.cs.illinois.edu> Date: Wed, 7 May 2025 17:48:02 -0500 Subject: [PATCH] finished client-side code --- mp3/Client/client.go | 196 ++++++++++++++++++++++++++++++++++++++ mp3/Makefile | 13 +++ mp3/Server/coordinator.go | 1 + mp3/Server/receiver.go | 1 + mp3/Server/server.go | 5 + 5 files changed, 216 insertions(+) create mode 100644 mp3/Client/client.go create mode 100644 mp3/Makefile create mode 100644 mp3/Server/coordinator.go create mode 100644 mp3/Server/receiver.go create mode 100644 mp3/Server/server.go diff --git a/mp3/Client/client.go b/mp3/Client/client.go new file mode 100644 index 0000000..3c580a5 --- /dev/null +++ b/mp3/Client/client.go @@ -0,0 +1,196 @@ +package main + +import ( + "bufio" + "encoding/gob" + "fmt" + "net" + "os" + "strconv" + "strings" +) + +type Client struct { + Name string // unique identifier for client + Connection net.Conn // tcp connection to server + Connected bool // true if established connection + Servers []string // server ip addresses and ports + ResponseChan chan Response // channel for responses from server +} + +type Request struct { + Transaction string // type of transaction + Branch string + Account string + Amount int +} + +type Response struct { + Result bool + Message bool +} + +func (client *Client) run_server() { + // place server responses into channel + for { + response := Response{} + dec := gob.NewDecoder(client.Connection) + dec.Decode(&response) + client.ResponseChan <- response + } +} + +func (client *Client) connect() { + request := Request{} + response := Response{} + + request.Transaction = "BEGIN" + request.Branch = client.Name + request.Account = client.Name + + for _, server := range client.Servers { + connection, err := net.Dial("tcp", server) + if err != nil { + continue + } + + // send connection request + enc := gob.NewEncoder(connection) + enc.Encode(&request) + // receive connection response + dec := gob.NewDecoder(connection) + dec.Decode(&response) + + if response.Result { + client.Connection = connection + client.ResponseChan <- response + go client.run_server() // start server if valid connection response + return + } + } + client.ResponseChan <- response +} + +func (client *Client) send_request(transaction string, account string, amount int) { + request := Request{} + request.Transaction = transaction + request.Amount = amount + + if transaction == "COMMIT" || transaction == "ABORT" { + request.Account = "" + request.Branch = "" + } else { + substrings := strings.Split(account, ".") + request.Account = substrings[1] + request.Branch = substrings[0] + } + + enc := gob.NewEncoder(client.Connection) + enc.Encode(&request) +} + +func (client *Client) read_file(config_name string) { + config, error := os.Open(config_name) + if error != nil { + fmt.Println("failed to open config") + return + } + + reader := bufio.NewReader(config) + + // assumption that only ever have 5 servers (no more, no less) + for i := 0; i < 5; i++ { + text, serr := reader.ReadString('\n') + substrings := strings.Split(text, " ") + if serr != nil && i < 4 { + fmt.Println("failed to read config") + } + // remove new line char from port + substrings[2] = strings.ReplaceAll(substrings[2], "\n", "") + + // formatteed server address as sp25-cs425-0601.cs.illinois.edu:1234 + client.Servers = append(client.Servers, substrings[1]+":"+substrings[2]) + } + + config.Close() +} + +func main() { + // init client + client := Client{ + Name: "", + ResponseChan: make(chan Response), + } + + // read config and attach server:port + client.read_file("config.txt") + reader := bufio.NewReader(os.Stdin) + + // get user inputs + for { + input, _ := reader.ReadString('\n') + substrings := strings.Split(input, " ") + + // handle user input + if substrings[0] == "BEGIN" { + // check if connection exists + if client.Connected { + continue + } + // setup server connection + go client.connect() + response := <-client.ResponseChan + if response.Result { + client.Connected = true + fmt.Println("OK") + } else { + fmt.Println("ABORTED") + return + } + } else if substrings[0] == "COMMIT" { + go client.send_request(substrings[0], "", 0) + response := <-client.ResponseChan + if response.Result { + fmt.Println("COMMIT OK") + return + } else { + fmt.Println("ABORTED") + return + } + } else if substrings[0] == "ABORT" { + go client.send_request(substrings[0], "", 0) + <-client.ResponseChan + fmt.Println("ABORTED") + return + } else if substrings[0] == "DEPOSIT" { + amount, _ := strconv.Atoi(substrings[2]) + go client.send_request(substrings[0], substrings[1], amount) + response := <-client.ResponseChan + if response.Result { + fmt.Println("OK") + } else { + fmt.Println("ABORTED") + return + } + } else if substrings[0] == "BALANCE" { + go client.send_request(substrings[0], substrings[1], 0) + response := <-client.ResponseChan + if response.Result { + fmt.Println(response.Message) + } else { + fmt.Println("NOT FOUND, ABORTED") + return + } + } else if substrings[0] == "WITHDRAW" { + amount, _ := strconv.Atoi(substrings[2]) + go client.send_request(substrings[0], substrings[1], amount) + response := <-client.ResponseChan + if response.Result { + fmt.Println("OK") + } else { + fmt.Println("NOT FOUND, ABORTED") + return + } + } + } +} diff --git a/mp3/Makefile b/mp3/Makefile new file mode 100644 index 0000000..c58ea65 --- /dev/null +++ b/mp3/Makefile @@ -0,0 +1,13 @@ +#!/bin/bash + +.PHONY: server client clean + +client : Client/client.go + go build -o client Client/client.go + +server : Server/server.go Server/coordinator.go Server/receiver.go + go build -o server Server/server.go Server/coordinator.go Server/receiver.go + +clean: + rm -f server client + diff --git a/mp3/Server/coordinator.go b/mp3/Server/coordinator.go new file mode 100644 index 0000000..4c7185b --- /dev/null +++ b/mp3/Server/coordinator.go @@ -0,0 +1 @@ +package Server diff --git a/mp3/Server/receiver.go b/mp3/Server/receiver.go new file mode 100644 index 0000000..4c7185b --- /dev/null +++ b/mp3/Server/receiver.go @@ -0,0 +1 @@ +package Server diff --git a/mp3/Server/server.go b/mp3/Server/server.go new file mode 100644 index 0000000..e6ac37b --- /dev/null +++ b/mp3/Server/server.go @@ -0,0 +1,5 @@ +package Server + +func main() { + +} -- GitLab