github.com/zhongdalu/gf@v1.0.0/g/os/gproc/gproc_comm_send.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  package gproc
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/json"
    12  	"errors"
    13  	"fmt"
    14  	"github.com/zhongdalu/gf/g/net/gtcp"
    15  	"github.com/zhongdalu/gf/g/os/gfcache"
    16  	"github.com/zhongdalu/gf/g/util/gconv"
    17  	"io"
    18  	"time"
    19  )
    20  
    21  const (
    22  	gPROC_COMM_FAILURE_RETRY_COUNT   = 3    // 失败重试次数
    23  	gPROC_COMM_FAILURE_RETRY_TIMEOUT = 1000 // (毫秒)失败重试间隔
    24  	gPROC_COMM_SEND_TIMEOUT          = 5000 // (毫秒)发送超时时间
    25  	gPROC_COMM_DEAFULT_GRUOP_NAME    = ""   // 默认分组名称
    26  )
    27  
    28  // 向指定gproc进程发送数据.
    29  func Send(pid int, data []byte, group ...string) error {
    30  	msg := Msg{
    31  		SendPid: Pid(),
    32  		RecvPid: pid,
    33  		Group:   gPROC_COMM_DEAFULT_GRUOP_NAME,
    34  		Data:    data,
    35  	}
    36  	if len(group) > 0 {
    37  		msg.Group = group[0]
    38  	}
    39  	msgBytes, err := json.Marshal(msg)
    40  	if err != nil {
    41  		return err
    42  	}
    43  	var buf []byte
    44  	var conn *gtcp.PoolConn
    45  	// 循环获取连接TCP对象
    46  	for i := gPROC_COMM_FAILURE_RETRY_COUNT; i > 0; i-- {
    47  		if conn, err = getConnByPid(pid); err == nil {
    48  			break
    49  		}
    50  		time.Sleep(gPROC_COMM_FAILURE_RETRY_TIMEOUT * time.Millisecond)
    51  	}
    52  	if conn == nil {
    53  		return err
    54  	}
    55  	defer conn.Close()
    56  	// 执行数据发送
    57  	buf, err = conn.SendRecvPkgWithTimeout(msgBytes, gPROC_COMM_SEND_TIMEOUT*time.Millisecond)
    58  	if len(buf) > 0 {
    59  		if !bytes.EqualFold(buf, []byte("ok")) {
    60  			err = errors.New(string(buf))
    61  		}
    62  	}
    63  	// EOF不算异常错误
    64  	if err == io.EOF {
    65  		err = nil
    66  	}
    67  	return err
    68  }
    69  
    70  // 获取指定进程的TCP通信对象
    71  func getConnByPid(pid int) (*gtcp.PoolConn, error) {
    72  	port := getPortByPid(pid)
    73  	if port > 0 {
    74  		if conn, err := gtcp.NewPoolConn(fmt.Sprintf("127.0.0.1:%d", port)); err == nil {
    75  			return conn, nil
    76  		} else {
    77  			return nil, err
    78  		}
    79  	}
    80  	return nil, errors.New(fmt.Sprintf("could not find port for pid: %d", pid))
    81  }
    82  
    83  // 获取指定进程监听的端口号
    84  func getPortByPid(pid int) int {
    85  	path := getCommFilePath(pid)
    86  	content := gfcache.GetContents(path)
    87  	return gconv.Int(content)
    88  }