当我在go中添加另一个阻塞线程时,为什么信号处理程序无效

时间:2015-09-09 07:53:21

标签: go signals

我正在尝试构建一个非常简单的tcp服务器/客户端。我希望程序可以在ctrl-c中断时关闭连接。

如果我只在主线程中发送消息或仅接收消息,一切正常。

以下是客户端的代码。

package main 

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "net"
    "bufio"
    "io"
    "time"
)

const (
    TIMEOUT = 10
)

func main() {
    if len(os.Args) < 2 {
        fmt.Println(usage(os.Args[0]))
        return
    }

    var timeout time.Duration
    if len(os.Args) > 2 {
        timeout, _ = time.ParseDuration(os.Args[2])
    }
    if timeout == 0 {
        timeout = time.Duration(TIMEOUT * time.Second)
    }

    conn, err := net.DialTimeout("tcp", os.Args[1], timeout)

    if err != nil {
        fmt.Println("Error connecting: ", err.Error())
        return
    }

    defer conn.Close()

    c := make(chan os.Signal, 1)
    signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)

    go func() {
        fmt.Println("wait ctrl-c")
        for _ = range c {
            fmt.Println("close on ctrl-c")
            conn.Close()
        }
    }()

    for {
        message, err := bufio.NewReader(os.Stdin).ReadString('\n')
        if err == io.EOF {
            fmt.Fprint(conn, message)
            break
        } else if err != nil {
            fmt.Println("Error reading: ", err.Error())
            break
        } else {
            fmt.Fprintf(conn, message)
        }
    }
}

func usage(filename string) string {
    return fmt.Sprintf("Usage: %s <address (ex. localhost:8016, google.com:http, [2001:db8::1]:http, etc.)> [timeout (ex. 10s, 300ms, etc.)]", filename)
}

但是在我添加了只打印它收到的代码并在另一个线程中运行它之后,ctrl-c处理程序不起作用。

这是代码:

package main 

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "net"
    "bufio"
    "io"
    "time"
)

const (
    TIMEOUT = 10
)

func main() {
    if len(os.Args) < 2 {
        fmt.Println(usage(os.Args[0]))
        return
    }

    var timeout time.Duration
    if len(os.Args) > 2 {
        timeout, _ = time.ParseDuration(os.Args[2])
    }
    if timeout == 0 {
        timeout = time.Duration(TIMEOUT * time.Second)
    }

    conn, err := net.DialTimeout("tcp", os.Args[1], timeout)

    if err != nil {
        fmt.Println("Error connecting: ", err.Error())
        return
    }

    defer conn.Close()

    c := make(chan os.Signal, 1)
    signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)

    go func() {
        fmt.Println("wait ctrl-c")
        for _ = range c {
            fmt.Println("close on ctrl-c")
            conn.Close()
        }
    }()
    // code added.
    go func() {
        for {
            message, err := bufio.NewReader(conn).ReadString('\n')
            if err == io.EOF {
                fmt.Print(message)
                break
            } else if err != nil {
                fmt.Println("Error remote reading: ", err.Error())
                break
            } else {
                fmt.Print(message)
            }
        }

        conn.Close()

        os.Exit(0)
    }()

    for {
        message, err := bufio.NewReader(os.Stdin).ReadString('\n')
        if err == io.EOF {
            fmt.Fprint(conn, message)
            break
        } else if err != nil {
            fmt.Println("Error reading: ", err.Error())
            break
        } else {
            fmt.Fprintf(conn, message)
        }
    }
}

func usage(filename string) string {
    return fmt.Sprintf("Usage: %s <address (ex. localhost:8016, google.com:http, [2001:db8::1]:http, etc.)> [timeout (ex. 10s, 300ms, etc.)]", filename)
}

我现在正在使用Windows 7。 有什么问题,如何解决?

您可以在此处找到服务器端和客户端代码: https://gist.github.com/programus/52591a97def30df9dc81

0 个答案:

没有答案