通過套接字連接發送 GUI/TUI (Sending a GUI/TUI Over a Socket Connection)


問題描述

通過套接字連接發送 GUI/TUI (Sending a GUI/TUI Over a Socket Connection)

最近我一直在嘗試用 golang 創建一個程序,它在服務器上運行,並接受 telnet 連接。然後我想打開一個 TUI(文本用戶界面),例如一個 curses 菜單(在 golang 的情況下,類似於:termuigocui 等)通過該 telnet 連接。我的問題是,我到底怎麼能做到這一點和/或什至有可能?我嘗試在接受連接時嘗試啟動 TUI,但它只是在服務器端打開它,而不是在 telnet 客戶端。據我所知,沒有簡單的方法通過 telnet 或任何其他套接字 IO 連接發送 TUI。

在試圖解決這個問題時,我們將不勝感激。謝謝!:D


參考解法

方法 1:

First, you should note that the example I give is completely insecure (don't expose it over the Internet!) and also doesn't provide for things like signal handling or resizing of the terminal (you may want to consider using SSH instead).

But to answer your question, here is an example of running a TCP server and connecting remote clients to a termui program running in a local PTY (uses both the https://github.com/gizak/termui and https://github.com/kr/pty packages):

package main

import (
    "flag"
    "io"
    "log"
    "net"
    "os"
    "os/exec"

    ui "github.com/gizak/termui"
    "github.com/kr/pty"
)

var termuiFlag = flag.Bool("termui", false, "run a termui example")

func main() {
    flag.Parse()

    var err error
    if *termuiFlag {
        err = runTermui()
    } else {
        err = runServer()
    }
    if err != nil {
        log.Fatal(err)
    }
}

// runTermui runs the termui "Hello World" example.
func runTermui() error {
    if err := ui.Init(); err != nil {
        return err
    }
    defer ui.Close()

    p := ui.NewParagraph("Hello World!")
    p.Width = 25
    p.Height = 5
    ui.Render(p)

    for e := range ui.PollEvents() {
        if e.Type == ui.KeyboardEvent {
            break
        }
    }

    return nil
}

// runServer listens for TCP connections on a random port and connects
// remote clients to a local PTY running the termui example.
func runServer() error {
    ln, err := net.Listen("tcp", "127.0.0.1:0")
    if err != nil {
        return err
    }
    defer ln.Close()
    log.Printf("Listening for requests on %v", ln.Addr())
    for {
        conn, err := ln.Accept()
        if err != nil {
            return err
        }
        log.Printf("Connecting remote client %v to termui", conn.RemoteAddr())
        go connectTermui(conn)
    }
}

// connectTermui connects a client connection to a termui process running in a
// PTY.
func connectTermui(conn net.Conn) {
    defer func() {
        log.Printf("Closing remote client %v", conn.RemoteAddr())
        conn.Close()
    }()

    t, err := pty.StartWithSize(
        exec.Command(os.Args[0], "‑‑termui"),
        &pty.Winsize{Cols: 80, Rows: 24},
    )
    if err != nil {
        log.Printf("Error starting termui: %v", err)
        return
    }
    defer t.Close()

    go io.Copy(t, conn)
    io.Copy(conn, t)
}

Example usage is to run this program in one window and connect to it using nc in another:

$ go run server.go
2019/01/18 01:39:37 Listening for requests on 127.0.0.1:56192
$ nc 127.0.0.1 56192

You should see the "Hello world" box (hit enter to disconnect).

(by jsmithlmars)

參考文件

  1. Sending a GUI/TUI Over a Socket Connection (CC BY‑SA 2.5/3.0/4.0)

#sockets #GO #linux #telnet #tui






相關問題

Ці павінен UDP-сокет праходзіць працэс прыняцця, як TCP-сокеты? (Does UDP socket need to go through the Accept Process like TCP sockets?)

як запусціць каманду openssl з прыкладання java (how to run openssl command from a java application)

TypeError: непадтрымоўваны сокет тыпу аперанда Python (TypeError: unsupported operand type-python socket)

套接字編程:某些 ISP 是否對 FTP 上傳施加了速率限制? (Socket programming: Do some ISP's impose rate-limiting on FTP uploads?)

兩個進程使用同一個端口? (Two processes using the same port?)

Akka TCP 客戶端:如何使用 akka actor 通過 TCP 發送消息 (Akka TCP client: How can I send a message over TCP using akka actor)

無法運行 python-bluez RFCOMM 服務器示例腳本 (Cannot run python-bluez RFCOMM server example script)

Java中的套接字和進程 (Sockets and Processes in Java)

在網絡環境中從 Brother TD-4100N 打印機檢索打印機狀態 (Retrieving the printer status from the Brother TD-4100N printer in a network environment)

通過套接字連接發送 GUI/TUI (Sending a GUI/TUI Over a Socket Connection)

如果服務器無法訪問,則在 android 上運行的客戶端將關閉並退出應用程序,無異常或函數“connect (socket)”中的任何消息 (the client running on android closes and exit application without exception or any message in function “connect (socket)” if the server is unreachable)

使用 C 的 select() 系統調用為 UDP 應用程序創建多個客戶端和一個服務器 (Creating Multiple Client and One Server for UDP application using select() system call with C)







留言討論