在grpc的编码中发现客户端stream流有方法。CloseSend() error
客户端如果想主动关闭连接直接调用此方法即可关闭,但是服务端对应的ServerStream没有关闭的方法,最后Google一下发现github grpc 项目中有对应的解答:https://github.com/grpc/grpc-go/issues/444
很简单服务端只需要跳出循环即可断开连接,下面贴出我的解决方案:
主动关闭的方法,向chan发送标志位。
func (s *Grpc_session) Close() {
close(s.WriteChan)
// 没有找到Serverstream关闭的方法,只能发送chan退出循环
s.exit <- true
}
这里直接用select接受chan,如果接受到则退出。
func DoWithTimeout(f func() (*Message, error), d time.Duration) (*Message, error) {
errChan := make(chan error, 1)
Message := make(chan *Message, 1)
go func() {
message, err := f()
if err != nil {
errChan <- err
} else {
Message <- message
}
//close(errChan)
}()
t := time.NewTimer(5 * time.Second)
select {
case <-t.C:
return nil, fmt.Errorf("slow")
case err := <-errChan:
if !t.Stop() {
<-t.C
return nil, err
}
case message := <-Message:
return message, nil
}
return nil, fmt.Errorf("slow")
}
func (s *Grpc_session) Run() error {
for {
select {
case <-s.exit:
return nil
default:
//in, err := s.Comminute_client.Recv()
in, err := DoWithTimeout(func() (*Message, error) { return stream.Recv() }, 5*time.Second)
if err == io.EOF {
fmt.Println("read done")
return nil
}
if err != nil {
fmt.Errorf("ERROR : %v", err)
return err
}
f, exit := func_manage.FunManage.Get(in.GetName())
if exit != nil {
fmt.Errorf("%v has not Register!", in.GetName())
continue
}
switch f.(type) {
case func(...interface{}):
go f.(func(...interface{}))(in, s)
case func(...interface{}) interface{}:
case func(...interface{}) []interface{}:
default:
fmt.Println("function id : definition of function is invalid")
}
}
}
}
在测试中,退出循环时客户端也收到服务端断开连接的标志,证明方案可行~~