import ( "fmt" "os" "os/signal" "time" ) var i int
funcinit() { go SignalHandler(make(chan os.Signal, 1)) } funcmain() { i = 0 for { i++ time.Sleep(time.Second) } }
funcSignalHandler(c chan os.Signal) { signal.Notify(c, os.Interrupt) for s:= <-c;; s= <-c { switch s { case os.Interrupt: fmt.Println("interrupt received", i) os.Exit(0) // 去掉这一行,那么Ctrl+c的快捷键将不能中断进程运行 default: fmt.Println("default case") } } }
运行上面的代码,在Ctrl-c时可以看到输出 interrupt received 字符串。
除了接收系统的信号,还可以向其他的进行发送信号。
syscall.Kill(syscall.Getpid(), syscall.SIGABRT)
这一部分可能暂时用不上,只要知道有这种用法就可以了。
TCP/IP
使用net提供的TCP/IP封装可以很方便的监听与请求端口。
server(src/wuxu/tcpserver/main.go):
package main
import ( "net" "fmt" ) var i int funcmain() { i = 0 if listener, e := net.Listen("tcp", ":1024"); e == nil { for { if conn, e := listener.Accept(); e==nil { gofunc(c net.Conn) { defer c.Close() fmt.Fprintln(c, "hihi", i) i++ }(conn) } } } else { fmt.Println("error") } }
client(src/wuxu/tcpclient/main.go)
package main
import ( "fmt" "net" "bufio" )
funcmain() { if conn, e := net.Dial("tcp", "localhost:1024"); e == nil { defer conn.Close() if text, e := bufio.NewReader(conn).ReadString('\n'); e ==nil { fmt.Println(text) } } else { fmt.Println("error", e) } }
加密的TCP通信
还可以很方便地简历加密的连接,为了加密连接我们需要两套密钥对,即服务器的公钥与私钥,客户端的公钥与私钥,使用之前的方法再在服务器和客户端的目录下,各生成一对密钥。go run $GOROOT/src/crypto/tls/generate_cert.go -ca=true -host="localhost" 修改代码如下:
server:
package main
import ( "fmt" "crypto/tls" "crypto/rand" ) var i int funcmain() { i = 0 var config tls.Config if certificate, e := tls.LoadX509KeyPair("cert.pem", "key.pem"); e ==nil { config = tls.Config{ Certificates: []tls.Certificate{certificate}, Rand: rand.Reader, } } if listener, e := tls.Listen("tcp", ":1024", &config); e == nil { for { if conn, e := listener.Accept(); e==nil { gofunc(c *tls.Conn) { defer c.Close() fmt.Fprintln(c, "secure hihi", i) i++ }(conn.(*tls.Conn)) } } } else { fmt.Println("error") } }
可以看出,引入tls包后不需要net包了,tls实现了相关得了协议的加密版本。
client:
package main
import ( "fmt" "bufio" "crypto/tls" )
funcmain() { var config tls.Config if certificate, e := tls.LoadX509KeyPair("cert.pem", "key.pem"); e == nil { config = tls.Config{ Certificates: []tls.Certificate{certificate}, InsecureSkipVerify: true, } } if conn, e := tls.Dial("tcp", "localhost:1024", &config); e == nil { defer conn.Close() if text, e := bufio.NewReader(conn).ReadString('\n'); e ==nil { fmt.Println(text) } } else { fmt.Println("error", e) } }
funcmain() { if addr, e := net.ResolveUDPAddr("udp", ":1026"); e == nil { if server, e := net.ListenUDP("udp", addr); e == nil { // infinit loop for buffer := MakeBuffer(); ; buffer = MakeBuffer() { if n, client, e := server.ReadFromUDP(buffer); e == nil { gofunc( c *net.UDPAddr, packet []byte) { if n, e := server.WriteToUDP(MSG, c); e == nil { Printf("%v bytes written to %v\n", n, c) } }(client, buffer[:n]) } else { Println("error1", e) } } } else { Println("error2", e) } } else { Println("error3", e) } }
var MSG = []byte("hello go scure udp") var RSA_LABEL = []byte("server")
funcmain() { Serve(":1025", func(conn *UDPConn, c *UDPAddr, packet *bytes.Buffer)(n int) { var key rsa.PublicKey if e := gob.NewDecoder(packet).Decode(&key); e==nil { if resp, e := rsa.EncryptOAEP(sha1.New(), rand.Reader, &key, MSG, RSA_LABEL); e==nil { n, _ = conn.WriteToUDP(resp, c) } } return }) }
funcServe(addr string, f func(*UDPConn, *UDPAddr, *bytes.Buffer)int) { Launch(addr, func(conn *UDPConn) { for { buffer := make([]byte, 1024) if n, client, e := conn.ReadFromUDP(buffer); e == nil { gofunc(c *UDPAddr, b []byte) { if n := f(conn, c, bytes.NewBuffer(b)); n!=0 { Println(n, "write to ", c) } }(client, buffer[:n]) } } }) }
funcLaunch(addr string, f func(*UDPConn)) { if a, e := ResolveUDPAddr("udp", addr); e == nil { if server, e := ListenUDP("udp", a); e == nil { f(server) } } }
funcmain() { Connect("localhost:1025", func(server *UDPConn, priKey *rsa.PrivateKey) { cipherText := MakeBuffer() if n, e := server.Read(cipherText); e == nil { Println("cipher text", string(cipherText)) // cipherText是加密的数据,需要解密 if plainText, e := rsa.DecryptOAEP(sha1.New(), rand.Reader, priKey, cipherText[:n], RSA_LABEL); e == nil { Println("receive decrypt string:", string(plainText)) } } }) }
funcConnect(address string, f func(*UDPConn, *rsa.PrivateKey)) { LoadPrivateKey("key.pem", func(pk *rsa.PrivateKey) { // pk is private key if addr, e := ResolveUDPAddr("udp", address); e ==nil { if server, e := DialUDP("udp", nil, addr); e == nil { defer server.Close() SendKey(server, pk.PublicKey, func() { f(server, pk) }) } else { Println("err1", e) } } else { Println("err2", e) } }) }
funcLoadPrivateKey(file string, f func(*rsa.PrivateKey)) { if file, e := ioutil.ReadFile(file); e == nil { if block, _ := pem.Decode(file); block != nil { if block.Type == "RSA PRIVATE KEY" { if key, _ := x509.ParsePKCS1PrivateKey(block.Bytes); key !=nil { f(key) } } } } else { Println(e) } return }
funcSendKey(server *UDPConn, publicKey rsa.PublicKey, f func()) { var encodedKey bytes.Buffer if e := gob.NewEncoder(&encodedKey).Encode(publicKey); e == nil { if _, e = server.Write(encodedKey.Bytes()); e == nil { f() } } }