Как эффективно закрыть две программы? - PullRequest
0 голосов
/ 27 декабря 2018

Я использую две одновременные программы для копирования stdin / stdout из моего терминала в цель net.Conn.По какой-то причине мне не удается полностью остановить две процедуры go без получения ошибки паники (для попытки закрыть закрытое соединение).Это мой код:

func interact(c net.Conn, sessionMap map[int]net.Conn) {
    quit := make(chan bool) //the channel to quit

    copy := func(r io.ReadCloser, w io.WriteCloser) {
        defer func() {
            r.Close()
            w.Close()
            close(quit) //this is how i'm trying to close it
        }()

        _, err := io.Copy(w, r)

        if err != nil {
            //
        }

    }

    go func() {
        for {
            select {
            case <-quit:
                return
            default:
                copy(c, os.Stdout)
            }
        }
    }()

    go func() {
        for {
            select {
            case <-quit:
                return
            default:
                copy(os.Stdin, c)
            }
        }
    }()
}

Это ошибка как panic: close of closed channel Я хочу завершить две процедуры go, а затем нормально перейти к другой функции.Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Также может быть так

 func scanReader(quit chan int, r io.Reader) chan string {
          line := make(chan string)
           go func(quit chan int) {
                    defer close(line)
                    scan := bufio.NewScanner(r)
                    for scan.Scan() {
                    select {
                       case <- quit:
                          return
                       default:
                          s := scan.Text()
                          line <- s
                    }
                    }
                }(quit)
               return line
    }

            stdIn := scanReader(quit, os.Stdin) 
            conIn := scanReader(quit, c) 
        for {
            select {
                    case <-quit:
                        return
                    case l <- stdIn:
                        _, e := fmt.Fprintf(c, l)
                        if e != nil {
                           quit <- 1
                           return
                        }
                    case l <- conIn:
                        fmt.Println(l)
                    }
        }
0 голосов
/ 27 декабря 2018

Вы не можете вызывать close на канале более одного раза, нет причин вызывать copy в цикле for, поскольку он может работать только один раз, и вы копируете в неправильном направлении, записываяв stdin и чтение из stdout.

Просто спросить, как выйти из 2-х программ, просто, но это не единственное, что вам нужно сделать здесь.Поскольку io.Copy блокирует, вам не нужна дополнительная синхронизация, чтобы определить, когда вызов завершен.Это позволяет значительно упростить код, что значительно упрощает рассуждения.

func interact(c net.Conn) {
    go func() {
        // You want to close this outside the goroutine if you
        // expect to send data back over a half-closed connection
        defer c.Close()

        // Optionally close stdout here if you need to signal the
        // end of the stream in a pipeline.
        defer os.Stdout.Close()

        _, err := io.Copy(os.Stdout, c)
        if err != nil {
            //
        }
    }()

    _, err := io.Copy(c, os.Stdin)
    if err != nil {
        //
    }
}

Также обратите внимание, что вы, возможно, не сможете вырваться из io.Copy из стандартного ввода, поэтому вы можетене ожидайте, что функция interact вернется.Вручную можно выполнить io.Copy в теле функции и проверить наличие полузамкнутого соединения в каждом цикле, тогда вы можете быстрее разорвать соединение и убедиться, что вы полностью закрыли net.Conn.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...