got full piecewise file transmission working

This commit is contained in:
2024-05-20 00:19:05 -04:00
parent 345d24ad6b
commit 13676c0a75
4 changed files with 338 additions and 6 deletions
BIN
View File
Binary file not shown.
+190
View File
@@ -0,0 +1,190 @@
// =============================================================================
// Auth: alex
// File: client.go
// Revn: 05-19-2024 0.2
// Func: ask server for a message of the day quote
//
// TODO: gut
// write
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-18-2024: gutted
// 05-19-2024: fixed
// commented
//
// =============================================================================
package main
import (
//"io" // io.EOF
"flag" // BoolVar, StringVar, Parse
"fmt" // Println
"net" // ResolveTCPAddr, DialTCP, conn.Write,Read
"os" // Exit
//"strconv" // Atoi, Itoa
//"strings" // Split
)
/*
// print errors if they occur, quit
func check( err error ) {
var errep string // declare error report string
switch err { // switch case over error input
case nil: // if there was no error
// then there was no error
errep = "err is nil"
case io.EOF: // if there was an End Of File error
errep = "Error: " + err.Error() // document error
conn.Close() // close connection
default: // anything besides those are a big deal
errep = "Fatal: " + err.Error()
}
var critical bool // declare critical error flag
// must be neither nil nor EOF
critical = err != nil && err != io.EOF
if critical { // XXX critical print
// TODO at some point, critical should be logging instead of
// printing, only verbose should print
fmt.Println( "check() -> ", errep )
}
if critical { // if there was a critical error
os.Exit( 1 ) // cut and run
}
}
// get server response and print
func handle( conn net.Conn ) {
var buffer [tsize]byte // create buffer to hold response
// read n bytes from server into buffer ( byte slice )
n, err := conn.Read( buffer[:] )
check( err ) // check for errors
// split recv'd message over @, separate header from message
msg := strings.Split( string( buffer[:n] ), "@" )
var resp string // declare response variable
switch msg[0] { // switch/case over the header
case "la": // /la/, list answer
if len( msg ) > 2 {
resp = "lr@"
} else {
// split recv'd message over newline to create quote list
quotes := strings.Split( msg[1], "\n" )
for p, v := range quotes { // iterate over quotes
// print num of quote, followed by that quote
fmt.Println( p + 1, "\t", v )
}
resp = "te@success"
}
default: // something undefined entirely
// TODO write out to file
//fmt.Println( "Message header not recognized" )
//fmt.Println( msg )
conn.Close() // TODO how important is this line
return // dead return, essentially lets program quit
}
// send formulated response back to server
_, err = conn.Write( []byte( resp ) )
check( err ) // make sure write worked
handle( conn ) // call handle again
}
*/
// quick check for errors
func check( err error ) {
if err != nil { // err should be nil, !nil is bad
// print error and ditch
fmt.Println( "fatal::", err )
os.Exit( 1 )
}
}
// level 4 handle
func handle( conn net.Conn ) {
// create byte array of pre-ordained size
buf := make( []byte, tsize )
// read from connection into byte array
_, err := conn.Read( buf )
check( err ) // routine check for errors
msg := string( buf ) // convert to string
/*
// iterate over message string
for p, c := range msg {
// cast char ( rune ) to string and see if it's the end char
if string( c ) == "|" {
// if end char, print everything BUT char and exit
fmt.Println( msg[:p] )
return
}
}
*/
// iterate over message string
for _, c := range msg {
// cast char ( rune ) to string and see if it's the end char
if string( c ) == "X" {
// if end char, print everything BUT char and exit
fmt.Println( msg )
return
}
}
fmt.Println( msg ) // if char is not found, print entire
handle( conn ) // message and recursively call level4
}
// globals
var tsize int
var dest string // provide a new destination ip and port
func main() {
// define flags
flag.IntVar( &tsize, "s", 10, "tx size" )
flag.StringVar( &dest, "ip", ":1300", "ip:port of server" )
flag.Parse() // process flags
service := dest // declare server ip:port
// create address object
addr, err := net.ResolveTCPAddr( "tcp", service )
check( err ) // check for errors
// make connection with object
conn, err := net.DialTCP( "tcp", nil, addr )
check( err ) // check for errors
//command := "lr@pls"
// write command to server, beginning transaction
//_, err = conn.Write( []byte( command ) )
//check( err ) // make sure write worked
handle( conn ) // handle response
// TODO stack trace when handle returns, should probably be
// updated
conn.Close() // close connection when finished
os.Exit( 0 ) // exit
}
Binary file not shown.
+148 -6
View File
@@ -1,11 +1,10 @@
// ============================================================================= // =============================================================================
// Auth: Alex Celani // Auth: Alex Celani
// File: test.go // File: test.go
// Revn: 05-13-2024 0.2 // Revn: 05-19-2024 0.4
// Func: explore bounding on piecewise file transmission ( PWFT ) // Func: explore bounding on piecewise file transmission ( PWFT )
// //
// TODO: rewrite makedata() to write to a file // TODO: implement
// write level4()
// ============================================================================= // =============================================================================
// CHANGE LOG // CHANGE LOG
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -15,22 +14,59 @@
// level 2 PWFT // level 2 PWFT
// 05-13-2024: comment level 1 and level 2 PWFT // 05-13-2024: comment level 1 and level 2 PWFT
// level 3 PWFT // level 3 PWFT
// 05-18-2024: began level 4 changes
// 05-19-2024: got level 4 working
// commented
// wrote level 5
// commented
// wrote level 6!
// commented
// //
// ============================================================================= // =============================================================================
package main package main
import ( import (
"flag"
"fmt" "fmt"
"math/rand" "math/rand"
"net" // ResovleTCPAddr, ListenTCP, listener.Accept
// conn.Read,Write
"os" // Exit
"strconv" "strconv"
) )
/*
func makedata() { func makedata() {
for c := 0; c < dsize; c++ { for c := 0; c < dsize; c++ {
datum[c] = rand.Intn( dsize ) datum[c] = rand.Intn( dsize )
} }
} }
*/
// special make function for strings
func makedatatx() {
// classic iteration of length dsize, toss in same-sized array
for c := 0; c < dsize; c++ {
// toss in same size array
// rand int picks letter, 0x61 -> lowercase ascii, cast byte
datumtx[c] = byte( rand.Intn( 26 ) + 0x61 )
}
// cast to string and print ( as slice )
fmt.Println( string( datumtx[:] ) )
}
// handle errors catastrophically
func check( err error ) {
if err != nil { // error is not nil on error
// print error
fmt.Println( "Fatal: ", err.Error() )
os.Exit( 1 ) // bail
}
}
// Levels of PWFT // Levels of PWFT
// 0. print everything indescriminately // 0. print everything indescriminately
@@ -41,6 +77,7 @@ func makedata() {
// 5. file tx piecewise with header // 5. file tx piecewise with header
// 6. file tx piecewise with variable header // 6. file tx piecewise with variable header
// level 0 PWFT // level 0 PWFT
func level0( data []int) { func level0( data []int) {
fmt.Println( data ) // level 0 sux fmt.Println( data ) // level 0 sux
@@ -108,19 +145,124 @@ func level3() {
} }
// level 4 PWFT
func level4( conn net.Conn ) {
txn := dsize / tsize // amount of transmissions
// iterate for number of transmissions
for c := 0; c < txn; c++ {
// write that amount of times, very specific slice
_, err := conn.Write( datumtx[c*tsize:(c+1)*tsize] )
check( err ) // routine error check
}
// write final of last chunk of data
_, err := conn.Write( datumtx[txn * tsize:] )
check( err ) // routine error check
_, err = conn.Write( []byte( "|" ) ) // write end char
check( err ) // routine error check
}
// level 5 PWFT
func level5( conn net.Conn ) {
header := "la@x@" // static header
psize := tsize - len( header ) // calculate payload size
txn := dsize / psize // amount of transmissions
// iterate for number of transmissions
for c := 0; c < txn; c++ {
// concat header with payload, easier as string, cast to byte
packet := header + string( datumtx[c*psize:(c+1)*psize] )
// write that amount of times, very specific slice
_, err := conn.Write( []byte( packet ) )
check( err ) // routine error check
}
// concat last payload
packet := header + string( datumtx[txn*psize:] )
// write final of last chunk of data
_, err := conn.Write( []byte( packet ) )
check( err ) // routine error check
_, err = conn.Write( []byte( "|" ) ) // write end char
check( err ) // routine error check
}
// level 6 PWFT
func level6( conn net.Conn ) {
var header string // declare header
var hhead, htail string = "la@", "@" // static pieces of header
txn := 1 // init transmission number
pos := 0 // init position tracker
for { // easier to do an infinite loop and break later
// combine both static parts of the header with the tx number
header = hhead + strconv.Itoa( txn ) + htail
hlen := len( header ) // keep track of total header length
// craft packet
packet := header + string( datumtx[pos:( pos + tsize - hlen )] )
// cast packet to byte array and send
_, err := conn.Write( []byte( packet ) )
check( err ) // routine error check
// update position as last position printed
pos = pos + tsize - hlen
txn++ // update transmission number
// check to see if *updated* position goes out of bounds
if pos + tsize - hlen > dsize {
break // break if'n
}
}
// print nth header ( X denotes final transmission )
header = hhead + "X" + htail
packet := header + string( datumtx[pos:] )
// cast data to string, concat, cast to byte array, send
_, err := conn.Write( []byte( packet ) )
check( err ) // routine error check
}
// size variables // size variables
var dsize int = 104 var dsize int = 104
// data global // data global
var datum = make( []int, dsize ) var datum = make( []int, dsize )
var datumtx = make( []byte, dsize )
var tsize int
func main() { func main() {
makedata() // fill global with data
flag.IntVar( &tsize, "s", 10, "tx size" )
flag.Parse()
makedatatx() // fill global with data
service := ":1300" // create service on ip and port
// resolve ip address and port
addr, err := net.ResolveTCPAddr( "tcp", service )
check( err ) // make sure ip resolves
// create listener object from ip:port
listener, err := net.ListenTCP( "tcp", addr )
// print global data to show that PWFT works as intended // print global data to show that PWFT works as intended
level0( datum ) //level0( datum )
level3() // do the thing //level3() // do the thing
for {
// wait, create connection when found
conn, err := listener.Accept()
check( err ) // make sure connection works
go level6( conn ) // handle connection
}
} }