github.com/zhongdalu/gf@v1.0.0/g/os/gproc/gproc_comm_receive.go (about) 1 // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 7 // "不要通过共享内存来通信,而应该通过通信来共享内存" 8 9 package gproc 10 11 import ( 12 "encoding/json" 13 "fmt" 14 "github.com/zhongdalu/gf/g/container/gqueue" 15 "github.com/zhongdalu/gf/g/container/gtype" 16 "github.com/zhongdalu/gf/g/net/gtcp" 17 "github.com/zhongdalu/gf/g/os/gfile" 18 "github.com/zhongdalu/gf/g/os/glog" 19 "github.com/zhongdalu/gf/g/util/gconv" 20 "net" 21 ) 22 23 const ( 24 gPROC_DEFAULT_TCP_PORT = 10000 // 默认开始监听的TCP端口号,如果占用则递增 25 gPROC_MSG_QUEUE_MAX_LENGTH = 10000 // 进程消息队列最大长度(每个分组) 26 ) 27 28 var ( 29 // 是否已开启TCP端口监听服务 30 tcpListened = gtype.NewBool() 31 ) 32 33 // 获取其他进程传递到当前进程的消息包,阻塞执行。 34 // 进程只有在执行该方法后才会打开请求端口,默认情况下不允许进程间通信。 35 func Receive(group ...string) *Msg { 36 // 一个进程只能开启一个监听goroutine 37 if !tcpListened.Val() && tcpListened.Set(true) == false { 38 go startTcpListening() 39 } 40 queue := (*gqueue.Queue)(nil) 41 groupName := gPROC_COMM_DEAFULT_GRUOP_NAME 42 if len(group) > 0 { 43 groupName = group[0] 44 } 45 if v := commReceiveQueues.Get(groupName); v == nil { 46 commReceiveQueues.LockFunc(func(m map[string]interface{}) { 47 if v, ok := m[groupName]; ok { 48 queue = v.(*gqueue.Queue) 49 } else { 50 queue = gqueue.New(gPROC_MSG_QUEUE_MAX_LENGTH) 51 m[groupName] = queue 52 } 53 }) 54 } else { 55 queue = v.(*gqueue.Queue) 56 } 57 58 if v := queue.Pop(); v != nil { 59 return v.(*Msg) 60 } 61 return nil 62 } 63 64 // 创建本地进程TCP通信服务 65 func startTcpListening() { 66 var listen *net.TCPListener 67 for i := gPROC_DEFAULT_TCP_PORT; ; i++ { 68 addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", i)) 69 if err != nil { 70 continue 71 } 72 listen, err = net.ListenTCP("tcp", addr) 73 if err != nil { 74 continue 75 } 76 // 将监听的端口保存到通信文件中(字符串类型存放) 77 if err := gfile.PutContents(getCommFilePath(Pid()), gconv.String(i)); err != nil { 78 glog.Error(err) 79 } 80 break 81 } 82 for { 83 if conn, err := listen.Accept(); err != nil { 84 glog.Error(err) 85 } else if conn != nil { 86 go tcpServiceHandler(gtcp.NewConnByNetConn(conn)) 87 } 88 } 89 } 90 91 // TCP数据通信处理回调函数 92 func tcpServiceHandler(conn *gtcp.Conn) { 93 option := gtcp.PkgOption{ 94 Retry: gtcp.Retry{ 95 Count: 3, 96 Interval: 10, 97 }, 98 } 99 for { 100 var result []byte 101 buffer, err := conn.RecvPkg(option) 102 if len(buffer) > 0 { 103 msg := new(Msg) 104 if err := json.Unmarshal(buffer, msg); err != nil { 105 glog.Error(err) 106 continue 107 } 108 if v := commReceiveQueues.Get(msg.Group); v == nil { 109 result = []byte(fmt.Sprintf("group [%s] does not exist", msg.Group)) 110 break 111 } else { 112 result = []byte("ok") 113 if v := commReceiveQueues.Get(msg.Group); v != nil { 114 v.(*gqueue.Queue).Push(msg) 115 } 116 } 117 } 118 if err == nil { 119 if err := conn.SendPkg(result, option); err != nil { 120 glog.Error(err) 121 } 122 } else { 123 if err := conn.Close(); err != nil { 124 glog.Error(err) 125 } 126 return 127 } 128 } 129 }