2017-12-01 3 views
2

Ich habe eine funktionierende TCP-Socket-Setup auf meinem Go-Server. Ich akzeptiere eine eingehende Verbindung, führe eine for-Schleife aus und lese eingehende Daten mit der Funktion net.Conn.Read.Was ist der richtige Weg zu verwenden net.Conn.Read für persistente TCP-Sockets

Aber es macht einfach keinen Sinn für mich. Woher weiß es, dass die vollständige Nachricht empfangen wurde, um mit der Rückgabe der Nachrichtengröße fortzufahren? derzeit

Dies ist mein Code:

func (tcpSocket *TCPServer) HandleConnection(conn net.Conn) { 

    println("Handling connection! ", conn.RemoteAddr().String(), " connected!")  
    recieveBuffer := make([]byte, 50) // largest message we ever get is 50 bytes 

    defer func() {   
     fmt.Println("Closing connection for: ", conn.RemoteAddr().String()) 
     conn.Close() 
    }() 

    for { 
     // how does it know the end of a message vs the start of a new one? 
     messageSize, err := conn.Read(recieveBuffer) 
     if err != nil { 
      return 
     } 
     if messageSize > 0 { // update keep alive since we got a message 
      conn.SetReadDeadline(time.Now().Add(time.Second * 5))  
     } 
    } 
} 

Können sagen, meine Anwendung eine Nachricht sendet, die 6 Bytes lang ist (kann beliebig groß sein). Wie weiß conn.Read, wenn es das Ende der Nachricht erhalten hat, um dann fortzufahren?

Meine Erfahrung liegt hauptsächlich in C#, also ist Go hier aber eher ungewöhnlich. Für meine C# -Anwendung haben die Nachrichten die Größe der Nachricht, die im ersten Byte enthalten ist, dann benutze ich eine for-Schleife, um die verbleibenden Bytes bis zur Nachrichtengröße zu lesen.

Noch scheint der obige Code in Go die volle Nachricht zu erhalten und fährt fort - es einige wie automatisch die Größe meiner Nachricht weiß?

Ich bin wirklich verwirrt, wie das passiert oder wenn es nur durch Glück arbeitet, wenn ich mich tatsächlich falsch annähere.

Alle meine Nachrichten haben die Überschrift im ersten Byte, die die Größe der Nachricht angibt. Aber es scheint, ich brauche es nicht auf einem Go-Server, verstehe ich nicht, wie das funktioniert?

+0

TCP funktioniert unabhängig von der Sprache. Es liegt an Ihnen, die Nachrichtengrenzen richtig zu handhaben. – JimB

+0

Also, warum verwenden alle Beispiele Read (someBuffer), da es nicht einmal solche Dinge behandelt? Wann würde Read jemals benutzt werden, wenn man ihm die Grenzen nicht sagen kann? Ich kann keine Beispiele finden, wie man es richtig macht. – WDUK

+0

Ich verstehe nicht, wie sonst würden Sie von einer TCP-Verbindung lesen? So funktioniert TCP, es ist ein Stream-Protokoll und es gibt einfach kein Konzept von Nachrichten. Wenn Sie Nachrichtenumschläge irgendeiner Art benötigen, verwenden Sie ein höheres Protokoll. – JimB

Antwort

3

TCP stellt keine Nachrichtenrahmen bereit, es liegt an Ihnen, den Stream zu puffern und die Nachrichten entsprechend dem von Ihnen definierten Protokoll zu analysieren.

Beim Parsen eines TCP-Streams ist es oft nützlich, die Verbindung sofort in eine bufio.Reader zu schreiben, da dies nicht nur das Lesen effizienter macht, sondern Ihnen auch nützlichere Methoden bietet. Ein Beispiel dafür, wie Sie Ihr Protokoll parsen könnten, könnte sein:

buff := make([]byte, 50) 
c := bufio.NewReader(conn) 

for { 
    // read a single byte which contains the message length 
    size, err := c.ReadByte() 
    if err != nil { 
     return err 
    } 

    // read the full message, or return an error 
    _, err := io.ReadFull(c, buff[:int(size)]) 
    if err != nil { 
     return err 
    } 

    fmt.Printf("received %x\n", buff[:int(size)]) 
} 
+0

Ah schön das sieht aus wie ich gesucht habe! Vielen Dank :) – WDUK

Verwandte Themen