En este artículo crearemos un cliente Netcat que nos servirá como interfaz en la terminal para un servidor de chat que estaremos implementando usando Go y el paquete Standar de Net
Para ello debemos entender que nos estaremos conectando usando el protocolo TCP y aprenderemos a usar Flags para poder enviar información a nuestro runtime de Go mediante parámetros en la terminal.
TCP es el Protocolo de Control de Transmisión que permite establecer una conexión y el intercambio de datos entre dos anfitriones. Este protocolo proporciona un transporte fiable de datos.
Un Flag es una entidad dentro del paquete flags que son extraídas de la ejecución del programa y que nos ayuda a hacer un programa de línea de comandos parametrizable.
Se ven de la siguiente forma en un programa ya compilado.
~./main --environment="dev"
Y así en un programa que no a sido construido aún.
~go run main.go --environment="dev"
En el código de nuestro programa se usan de la siguiente forma.
~package main import "flag" var env *string func init() { env = flag.String("env","production","our execution environment ") } func main() { flag.Parse() println(*env) }
Nuestra estrategia consistirá en lo siguiente obtener por flags los parámetros del host y port en primer lugar.
~package main import ( "flag" ) var ( host *string port *int ) func init() { host = flag.String("h", "localhost", "hostname") port = flag.Int("p", 3090, "port") } func main() { flag.Parse() }
Luego definir un método que copiará el contenido de nuestra comunicación.
~func CopyContent(dst io.Writer, src io.Reader) { if _, err := io.Copy(dst, src); err != nil { log.Fatal(err) } }
Y ahora en la función main nos conectaremos al servidor de TCP y enviaremos y obtendremos información.
~package main import ( "flag" "fmt" "io" "log" "net" "os" ) var ( host *string port *int ) func init() { host = flag.String("h", "localhost", "hostname") port = flag.Int("p", 3090, "port") } func main() { flag.Parse() conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", *host, *port)) if err != nil { log.Fatal(err) } log.Print("Connected") done := make(chan struct{}) go func() { io.Copy(os.Stdout, conn) done <- struct{}{} }() CopyContent(conn, os.Stdin) conn.Close() <-done } func CopyContent(dst io.Writer, src io.Reader) { if _, err := io.Copy(dst, src); err != nil { log.Fatal(err) } }
Con este simple programa podremos conectador a un servidor TCP y esperar nuevos mensajes para imprimir el contenido en pantalla, a su vez enviar contenido por consola hacia el servidor de TCP.