func(p*parser)recvMsg(maxReceiveMessageSizeint)(pfpayloadFormat,msg[]byte,errerror){if_,err:=p.r.Read(p.header[:]);err!=nil{return0,nil,err}pf=payloadFormat(p.header[0])length:=binary.BigEndian.Uint32(p.header[1:])iflength==0{returnpf,nil,nil}ifint64(length)>int64(maxInt){return0,nil,status.Errorf(codes.ResourceExhausted,"grpc: received message larger than max length allowed on current machine (%d vs. %d)",length,maxInt)}ifint(length)>maxReceiveMessageSize{return0,nil,status.Errorf(codes.ResourceExhausted,"grpc: received message larger than max (%d vs. %d)",length,maxReceiveMessageSize)}// TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead// of making it for each message:msg=make([]byte,int(length))if_,err:=p.r.Read(msg);err!=nil{iferr==io.EOF{err=io.ErrUnexpectedEOF}return0,nil,err}returnpf,msg,nil}
可以看到在Recv的时候判定了两次数据长度。
除了设置的长度外还有一个最大长度限制int64(length) > int64(maxInt)
1
2
3
4
5
6
ifint64(length)>int64(maxInt){return0,nil,status.Errorf(codes.ResourceExhausted,"grpc: received message larger than max length allowed on current machine (%d vs. %d)",length,maxInt)}ifint(length)>maxReceiveMessageSize{return0,nil,status.Errorf(codes.ResourceExhausted,"grpc: received message larger than max (%d vs. %d)",length,maxReceiveMessageSize)}
func(cs*clientStream)SendMsg(minterface{})(errerror){deferfunc(){iferr!=nil&&err!=io.EOF{// Call finish on the client stream for errors generated by this SendMsg// call, as these indicate problems created by this client. (Transport// errors are converted to an io.EOF error in csAttempt.sendMsg; the real// error will be returned from RecvMsg eventually in that case, or be// retried.)cs.finish(err)}}()ifcs.sentLast{returnstatus.Errorf(codes.Internal,"SendMsg called after CloseSend")}if!cs.desc.ClientStreams{cs.sentLast=true}// load hdr, payload, datahdr,payload,data,err:=prepareMsg(m,cs.codec,cs.cp,cs.comp)iferr!=nil{returnerr}// TODO(dfawley): should we be checking len(data) instead?iflen(payload)>*cs.callInfo.maxSendMessageSize{returnstatus.Errorf(codes.ResourceExhausted,"trying to send message larger than max (%d vs. %d)",len(payload),*cs.callInfo.maxSendMessageSize)}msgBytes:=data// Store the pointer before setting to nil. For binary logging.op:=func(a*csAttempt)error{err:=a.sendMsg(m,hdr,payload,data)// nil out the message and uncomp when replaying; they are only needed for// stats which is disabled for subsequent attempts.m,data=nil,nilreturnerr}err=cs.withRetry(op,func(){cs.bufferForRetryLocked(len(hdr)+len(payload),op)})ifcs.binlog!=nil&&err==nil{cs.binlog.Log(&binarylog.ClientMessage{OnClientSide:true,Message:msgBytes,})}return}
同理发送的时候也有这个限制
1
2
3
iflen(payload)>*cs.callInfo.maxSendMessageSize{returnstatus.Errorf(codes.ResourceExhausted,"trying to send message larger than max (%d vs. %d)",len(payload),*cs.callInfo.maxSendMessageSize)}