gitee.com/KyleChenSource/lib-robot@v1.0.2/robottest/robot/net/network_tcp.go (about)

     1  package net
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net"
     7  	"sync"
     8  
     9  	"gitee.com/KyleChenSource/lib-robot/robottest/common"
    10  	"gitee.com/KyleChenSource/lib-robot/robottest/protos"
    11  )
    12  
    13  // 接口都只允许在一个goroutine中调用
    14  type ClientTcp struct {
    15  	_handler    IClientHandler
    16  	_msglen_get MsgLenGet
    17  	_msgmin_get MsgMinGet
    18  	_msg_decode MsgDecode
    19  	_msg_encode MsgEncode
    20  	_tcp        *net.TCPConn
    21  
    22  	_join    *sync.WaitGroup // 用来等待开启的协程结束
    23  	_closing bool            // 正在关闭中标记位。因为chan的容量,导致了关闭可能死锁
    24  }
    25  
    26  func (this *ClientTcp) Initialize(h IClientHandler, func_msglen_get MsgLenGet, func_msgmin_get MsgMinGet, func_msg_decode MsgDecode, func_msg_encode MsgEncode) error {
    27  	this._handler = h
    28  	this._msglen_get = func_msglen_get
    29  	this._msgmin_get = func_msgmin_get
    30  	this._msg_decode = func_msg_decode
    31  	this._msg_encode = func_msg_encode
    32  
    33  	return nil
    34  }
    35  
    36  func (this *ClientTcp) co_recv() {
    37  	defer func() {
    38  		this._join.Done()
    39  	}()
    40  	defer common.PanicLog(func() {
    41  		this._handler.MsgChannel() <- &Msg{
    42  			Type: MSGTYPE_ERR,
    43  			Err:  fmt.Errorf("recv panic error"),
    44  		}
    45  	})
    46  
    47  	minlen := this._msgmin_get()
    48  	minBuf := make([]byte, minlen)
    49  	rl := 0 // 目前接收数据长度
    50  	for {
    51  		r, err := this._tcp.Read(minBuf[rl:])
    52  		if err != nil {
    53  			this._handler.MsgChannel() <- &Msg{
    54  				Type: MSGTYPE_ERR,
    55  				Err:  err,
    56  			}
    57  			break
    58  		}
    59  
    60  		if r == 0 {
    61  			this._handler.MsgChannel() <- &Msg{
    62  				Type: MSGTYPE_ERR,
    63  				Err:  fmt.Errorf("disconnected by remote"),
    64  			}
    65  			break
    66  		}
    67  
    68  		rl += r
    69  		if rl < minlen {
    70  			continue
    71  		}
    72  
    73  		msglen, err := this._msglen_get(minBuf)
    74  		if err != nil {
    75  			this._handler.MsgChannel() <- &Msg{
    76  				Type: MSGTYPE_ERR,
    77  				Err:  err,
    78  			}
    79  			break
    80  		}
    81  
    82  		msgBuf := make([]byte, msglen)
    83  		copy(msgBuf, minBuf)
    84  
    85  		if msglen <= minlen {
    86  			// 包已经足够大
    87  			copy(minBuf, minBuf[msglen:])
    88  			rl = minlen - msglen
    89  		} else {
    90  			rl = 0
    91  			_, err = io.ReadFull(this._tcp, msgBuf[minlen:])
    92  			if err != nil {
    93  				this._handler.MsgChannel() <- &Msg{
    94  					Type: MSGTYPE_ERR,
    95  					Err:  err,
    96  				}
    97  				break
    98  			}
    99  		}
   100  
   101  		// protoId, err := this._msg_decodeprotoid(msgBuf)
   102  		// if err != nil {
   103  		// 	this._handler.MsgChannel() <- &Msg{
   104  		// 		Type: MSGTYPE_ERR,
   105  		// 		Err:  err,
   106  		// 	}
   107  		// 	break
   108  		// }
   109  
   110  		// switch this._msg_filtertype {
   111  		// case ProtoFilterType_Focus:
   112  		// 	_, ok := this._msg_filter.Load(protoId)
   113  		// 	if !ok {
   114  		// 		continue
   115  		// 	}
   116  		// default:
   117  		// 	_, ok := this._msg_filter.Load(protoId)
   118  		// 	if ok {
   119  		// 		continue
   120  		// 	}
   121  		// }
   122  
   123  		// protoId, header, data, err := this._msg_decode(msgBuf)
   124  		// if err != nil {
   125  		// 	this._handler.MsgChannel() <- &Msg{
   126  		// 		Type: MSGTYPE_ERR,
   127  		// 		Err:  err,
   128  		// 	}
   129  		// 	break
   130  		// }
   131  
   132  		this._handler.MsgChannel() <- &Msg{
   133  			Type: MSGTYPE_RECV,
   134  			Data: msgBuf,
   135  		}
   136  	}
   137  }
   138  
   139  func (this *ClientTcp) connect(addr string) {
   140  	defer common.PanicLog(func() {
   141  		this._handler.MsgChannel() <- &Msg{
   142  			Type: MSGTYPE_ERR,
   143  			Err:  fmt.Errorf("connect panic error"),
   144  		}
   145  	})
   146  
   147  	tcp, err := net.Dial("tcp", addr)
   148  	if err != nil {
   149  		this._handler.MsgChannel() <- &Msg{
   150  			Type: MSGTYPE_ERR,
   151  			Err:  err,
   152  		}
   153  		this._join.Done()
   154  		return
   155  	}
   156  
   157  	this._tcp = tcp.(*net.TCPConn)
   158  	err = this._tcp.SetLinger(5)
   159  	if err != nil {
   160  		this._handler.MsgChannel() <- &Msg{
   161  			Type: MSGTYPE_ERR,
   162  			Err:  err,
   163  		}
   164  		this._join.Done()
   165  		return
   166  	}
   167  
   168  	this._handler.MsgChannel() <- &Msg{
   169  		Type: MSGTYPE_CONNECTED,
   170  	}
   171  
   172  	go this.co_recv()
   173  }
   174  
   175  func (this *ClientTcp) Start(addr string) error {
   176  	// 不能使用this._tcp作为判断,因为连接过程中_tcp == nil
   177  	if this._join != nil {
   178  		return fmt.Errorf("ClientTcp Not Close")
   179  	}
   180  
   181  	this._closing = false
   182  
   183  	this._join = &sync.WaitGroup{}
   184  	this._join.Add(1)
   185  	go this.connect(addr)
   186  
   187  	return nil
   188  }
   189  
   190  func (this *ClientTcp) join() {
   191  	if this._join != nil {
   192  		this._join.Wait()
   193  		this._join = nil
   194  	}
   195  
   196  	this._tcp = nil
   197  
   198  	this._handler.MsgChannel() <- &Msg{
   199  		Type: MSGTYPE_CLOSED,
   200  	}
   201  }
   202  
   203  func (this *ClientTcp) Close() {
   204  	if this._closing {
   205  		return
   206  	}
   207  
   208  	this._closing = true
   209  	if this._tcp != nil {
   210  		this._tcp.Close()
   211  	}
   212  
   213  	go this.join()
   214  }
   215  
   216  func (this *ClientTcp) Send(protoId protos.ProtoID, data protos.JsonString) error {
   217  	bytes, err := this._msg_encode(protoId, data)
   218  	if err != nil {
   219  		return err
   220  	}
   221  
   222  	l := len(bytes)
   223  	for l > 0 {
   224  		s, err := this._tcp.Write(bytes)
   225  		if err != nil {
   226  			this._handler.MsgChannel() <- &Msg{
   227  				Type: MSGTYPE_ERR,
   228  				Err:  err,
   229  			}
   230  			return err
   231  		}
   232  
   233  		l -= s
   234  		bytes = bytes[s:]
   235  	}
   236  
   237  	return nil
   238  }