2019-01-17 21:45

通过套接字连接发送GUI / TUI


Recently I have been trying to create a program in golang, which runs on a server, and accepts telnet connections. I would then like to open a TUI (text user interface) such as a curses menu (in the case of golang, something like: termui, gocui, etc) over that telnet connection. My question is, how exactly could I do this and/or would it even be possible? I have played around trying to start TUIs when a connection is accepted, but it just opens it on the server side, not on the telnet client side. From what I can tell, there is no easy way to just send a TUI over a telnet or any other socket IO connection for that matter.

Any help is appreciated in trying to figure this out. Thanks! :D

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答


  • dsa1234569 dsa1234569 2年前

    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 and packages):

    package main
    import (
        ui ""
    var termuiFlag = flag.Bool("termui", false, "run a termui example")
    func main() {
        var err error
        if *termuiFlag {
            err = runTermui()
        } else {
            err = runServer()
        if err != nil {
    // 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
        for e := range ui.PollEvents() {
            if e.Type == ui.KeyboardEvent {
        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", "")
        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())
        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)
        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
    $ nc 56192

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

    点赞 评论 复制链接分享