gtcp 模块支持 TLS 加密通信服务端及客户端,在对安全要求比较高的场景中非常必要。 TLS 服务端创建可以通过 NewServerTLS 或者 NewServerKeyCrt 方法实现。 TLS 客户端创建可以通过 NewConnKeyCrt 或者 NewConnTLS 方法实现。

    使用示例:

    https://github.com/gogf/gf/v2/tree/master/.example/net/gtcp/tls

    1. package main
    2. import (
    3. "fmt"
    4. "github.com/gogf/gf/v2/frame/g"
    5. "github.com/gogf/gf/v2/net/gtcp"
    6. "github.com/gogf/gf/v2/util/gconv"
    7. "time"
    8. )
    9. func main() {
    10. address := "127.0.0.1:8999"
    11. crtFile := "server.crt"
    12. keyFile := "server.key"
    13. // TLS Server
    14. go gtcp.NewServerKeyCrt(address, crtFile, keyFile, func(conn *gtcp.Conn) {
    15. defer conn.Close()
    16. for {
    17. data, err := conn.Recv(-1)
    18. if len(data) > 0 {
    19. fmt.Println(string(data))
    20. }
    21. if err != nil {
    22. // if client closes, err will be: EOF
    23. g.Log().Error(err)
    24. break
    25. }
    26. }
    27. }).Run()
    28. time.Sleep(time.Second)
    29. // Client
    30. conn, err := gtcp.NewConnKeyCrt(address, crtFile, keyFile)
    31. if err != nil {
    32. panic(err)
    33. }
    34. defer conn.Close()
    35. for i := 0; i < 10; i++ {
    36. if err := conn.Send([]byte(gconv.String(i))); err != nil {
    37. g.Log().Error(err)
    38. }
    39. time.Sleep(time.Second)
    40. if i == 5 {
    41. conn.Close()
    42. break
    43. }
    44. }
    45. // exit after 5 seconds
    46. time.Sleep(5 * time.Second)
    47. }

    执行后,可以看到客户端执行时报错:

    1. panic: x509: certificate has expired or is not yet valid

    那是因为我们的证书是手动创建的,并且已经过期了,为了演示方便,我们在客户端代码中去掉客户端对证书的校验。

    1. package main
    2. import (
    3. "fmt"
    4. "github.com/gogf/gf/v2/net/gtcp"
    5. "github.com/gogf/gf/v2/util/gconv"
    6. "time"
    7. )
    8. func main() {
    9. address := "127.0.0.1:8999"
    10. crtFile := "server.crt"
    11. keyFile := "server.key"
    12. // TLS Server
    13. go gtcp.NewServerKeyCrt(address, crtFile, keyFile, func(conn *gtcp.Conn) {
    14. defer conn.Close()
    15. for {
    16. data, err := conn.Recv(-1)
    17. if len(data) > 0 {
    18. fmt.Println(string(data))
    19. }
    20. if err != nil {
    21. // if client closes, err will be: EOF
    22. g.Log().Error(err)
    23. break
    24. }
    25. }
    26. }).Run()
    27. time.Sleep(time.Second)
    28. // Client
    29. tlsConfig, err := gtcp.LoadKeyCrt(crtFile, keyFile)
    30. if err != nil {
    31. panic(err)
    32. }
    33. tlsConfig.InsecureSkipVerify = true
    34. conn, err := gtcp.NewConnTLS(address, tlsConfig)
    35. if err != nil {
    36. panic(err)
    37. }
    38. defer conn.Close()
    39. for i := 0; i < 10; i++ {
    40. if err := conn.Send([]byte(gconv.String(i))); err != nil {
    41. g.Log().Error(err)
    42. }
    43. time.Sleep(time.Second)
    44. if i == 5 {
    45. conn.Close()
    46. break
    47. }
    48. }
    49. // exit after 5 seconds
    50. time.Sleep(5 * time.Second)
    51. }

    执行后,终端输出结果为:

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 2019-06-05 00:13:12.488 [ERRO] EOF
    7. Stack:
    8. 1. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/net/gtcp/tls/gtcp_server_client.go:25

    其中客户端在 5 秒后关闭了连接,因此服务端在接收数据时获取到了一个 EOF 错误,这种错误在正式使用中我们直接忽略,报错时服务端直接关闭客户端连接即可。