golangはtcp論理粘着パケットとプロトコルフローサイズに対する制約論理を解決する
7196 ワード
tcpデータストリームは受信者のbufサイズが不足している場合、論理的な接着パケットが発生する可能性があり、bufferを使用して接続が完了する前に単一ストリームメッセージを制限する時間が大きいことを確保することができ、手動で[]byteで1つのbufferを実現した.単一の要求では、EOF前のnサイズを読むたびに、しきい値を超えると、アラームが拒否される.この方法は実は愚かで、少なくともナイフのしきい値を読み取る前に、すべて受け入れられる.
実際には、プロトコルが[4]byte全長[4]byteヘッダ長[4]byteヘッダ長[]byteヘッダ長[]byteヘッダ[]byteヘッダ[]byteヘッダ[]byte body長[]byteヘッダ[]byte body
では、読み取り中に値が超えたかどうかを動的に判断するよりも、[4]byteで全長の値>しきい値を受け入れ、直接アラームが拒否されると、この論理的不正要求は、しきい値サイズを読み取るのではなく、最大12ビットを読み取ることである.
一般に総長は自己の[4]byteを含まないので,厳密な論理は総長の値>しきい値+4であるが,この制限は弱く一致し,邪魔にならない!
具体的な実現は以下の通りである.
実際には、プロトコルが[4]byte全長[4]byteヘッダ長[4]byteヘッダ長[]byteヘッダ長[]byteヘッダ[]byteヘッダ[]byteヘッダ[]byte body長[]byteヘッダ[]byte body
では、読み取り中に値が超えたかどうかを動的に判断するよりも、[4]byteで全長の値>しきい値を受け入れ、直接アラームが拒否されると、この論理的不正要求は、しきい値サイズを読み取るのではなく、最大12ビットを読み取ることである.
一般に総長は自己の[4]byteを含まないので,厳密な論理は総長の値>しきい値+4であるが,この制限は弱く一致し,邪魔にならない!
具体的な実現は以下の通りである.
func UnpackToBlockFromReader(reader io.Reader, maxLength int32) ([]byte, error) {
if reader == nil {
return nil, errors.New("reader is nil")
}
var info = make([]byte, 4, 4)
n, e := reader.Read(info)
if e != nil {
return nil, e
}
if n != 4 {
return nil, errors.New("can't read 4 length info block from reader, but read " + strconv.Itoa(n))
}
length:= binary.BigEndian.Uint32(info[0:4])
if length >= maxLength {
return info, errors.New(fmt.Sprintf("beyond max size limit %d but got %d", maxLength, length))
}
var content = make([]byte, length, length)
n, e = reader.Read(content)
if e != nil {
return nil, e
}
if n != int(length) {
return nil, errors.New(fmt.Sprintf("can't read %d length content block from reader, but read %d", length, n))
}
return append(info, content ...), nil
}