TCP ソケットに対する Go の読み取り関数を理解する
永続的な TCP ソケットに関して、重要な側面の 1 つは受信データの処理です。効果的に。 net.Conn.Read 関数はこの目的で一般的に使用されますが、メッセージ境界をどのように決定するかについて疑問が生じます。
TCP メッセージ フレーム
他の通信プロトコルとは異なります。 , TCP は本質的にメッセージ フレーミングを提供しません。メッセージの境界を示す区切り文字を持たずに、データを連続したバイト ストリームとして扱います。したがって、フレーム化メカニズムを定義して実装するのはアプリケーション層の責任です。
Go のアプローチ
Go の net.Conn の実装では、メッセージ フレーム化が次で処理されることを前提としています。アプリケーションレベル。これにより、アプリケーションは生のバイト ストリームを読み取り、定義されたプロトコルに基づいてそれを解釈できます。
使用例
質問で提供されているコードは、次を使用してデータを受信する方法を示しています。ループ内の net.Conn.Read:
func (tcpSocket *TCPServer) HandleConnection(conn net.Conn) { for { // Read message size and data without any message framing messageSize, err := conn.Read(recieveBuffer) if err != nil { return } // ... } }
この問題は、コードがメッセージ サイズを明示的に定義していないために発生します。
解決策: Bufio Reader と手動解析
この問題に対処するには、TCP 接続を bufio.Reader でラップすることをお勧めします。これにより、ストリームを解析するためのより効率的で便利な方法が提供されます。 bufio.Reader を使用してメッセージ フレーミングを実装する方法の例:
buff := make([]byte, 50) c := bufio.NewReader(conn) for { // Read message length from the first byte size, err := c.ReadByte() if err != nil { return err } // Read the remaining message data _, err := io.ReadFull(c, buff[:int(size)]) if err != nil { return err } fmt.Printf("Received %x\n", buff[:int(size)]) }
この例では、最初に 1 バイトを読み取り、メッセージ サイズを決定します。次に、io.ReadFull を使用してメッセージの残りのバイトを読み取ります。このアプローチにより、明示的なメッセージ フレーム化が提供され、さまざまなサイズのメッセージを処理できるようになります。
TCP メッセージ フレーム化の仕組みを理解し、bufio.Reader などの適切なツールを利用することで、永続的な TCP ソケット上の受信データを効果的に処理できます。行きましょう
以上がGo の「net.Conn.Read」関数は TCP メッセージ境界をどのように処理しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。