Go Socket TCP

TCP is a connection-oriented (a connection must be established before data transmission: TCP three-way handshake), reliable, byte-stream-based transport layer protocol. Data is transmitted like a continuous flow, which can lead to the problem of packet sticking.

TCP Server

A TCP server can simultaneously connect to many clients. In the Go language, creating multiple goroutines to achieve concurrency is convenient and efficient, so a goroutine is created to handle each established connection. The processing flow of a TCP server:

  1. Listen on a port
  2. Receive client requests and establish connections
  3. Create goroutines to handle connections
import (
    "bufio"
    "fmt"
    "net"
)
func main() {
    //Listen on a port
    listener, err := net.Listen("tcp", "localhost:8080")
    if err != nil {
        fmt.Println("Error listening:", err.Error())
        return
    }
    defer listener.Close()
    fmt.Println("Listening on: 8080")
    
    //Receive client requests
    for {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Println("Error accepting:", err.Error())
            continue
        }
        //Handle connections in the new goroutines
        go process(conn)
    }
}
// Process client connections
func process(conn net.Conn) {
    defer conn.Close()
    
    //Read data from the client
    message, err := bufio.NewReader(conn).ReadString('\n')
    if err != nil {
        fmt.Println("Error reading:", err.Error())
        return
    }
    fmt.Println("Message received:", message)
    
    //Send responses to the client
    _, err = conn.Write([]byte("Message received: " + message))
    if err != nil {
        fmt.Println("Error writing to the client:", err.Error())
        return
    }
}

TCP Client

The process of a TCP client for TCP communication:

  1. Establish a connection with the server
  2. Send and receive data
  3. Close the connection
import (
    "bufio"
    "fmt"
    "net"
    "os"
    "strings"
)
func main() {
    //Connecting to the Server
    conn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        fmt.Println("Error connecting:", err.Error())
        return
    }
    defer conn.Close()
    fmt.Println("Connected to server")
    
    //Read user input
    reader := bufio.NewReader(os.Stdin)
    for {
        fmt.Print("Enter message: ")
        message, _ := reader.ReadString('\n')
        
        //Remove whitespace characters (such as spaces, tabs, newlines, etc.) before sending the message
        message = strings.TrimSpace(message)
        if message == "exit" || message == "quit" {
            return
        }
        //Since all whitespace has been removed, explicitly add back "\n" here to let the server know when the message ends
        message += "\n"
  
        //Send the message to the server
        _, err := conn.Write([]byte(message))
        if err != nil {
            fmt.Println("Error writing:", err.Error())
            return
        }
        
        //Read the response from the server
        response, err := bufio.NewReader(conn).ReadString('\n')
        if err != nil {
            fmt.Println("Error reading:", err.Error())
            return
        }
        fmt.Print("Server response:", response)
    }
}

The Process of TCP Three-Way Handshake

First Handshake

  1. The client sends a TCP SYN packet (SYN=1) to the server, which includes a randomly generated sequence number (seq=client_seq).
  2. The client enters the SYN_SENT state, waiting for a response from the server.

SYN=1,seq=client_seq

Second Handshake

  1. Upon receiving the SYN packet, the server must send an ACK packet (ACK=1) to acknowledge receipt of the client's SYN packet (ack=client_seq + 1).
  2. Simultaneously, the server also sends its own SYN packet (SYN=1), including a randomly generated sequence number (seq=server_seq).
  3. The server enters the SYN_RECV state.

SYN=1,ACK=1,seq=server_seq,ack=client_seq + 1

Third Handshake

  1. After receiving the SYN+ACK packet from the server, the client sends an ACK packet (ACK=1) to acknowledge receipt of the server's SYN packet (ack=server_seq + 1).
  2. The client sets its sequence number to one more than the sequence number from the first handshake (seq=client_seq + 1).

ACK=1,seq=client_seq + 1,ack=server_seq + 1。At this point, both the client and the server enter the ESTABLISHED state, and the connection establishment is complete.

The Purpose of TCP Three-Way Handshake

First Handshake

  1. The client sends a network packet, and the server receives it.
  2. The server concludes (i.e., whoever receives, whoever confirms): The client's sending capability is normal.

Second Handshake

  1. The server sends a packet, and the client receives it.
  2. The client concludes: The server's receiving and sending capabilities are normal. However, at this point, the server cannot confirm whether the client's receiving capability is normal.

Third Handshake

  1. The client sends a packet, and the server receives it.
  2. The server finally concludes: The client's receiving capability is normal.

Therefore, three handshakes are required to confirm that both parties' receiving and sending capabilities are normal.

 

Take a break

👉👉👉 【BTTH Year EP107】Xiao Yan successfully refined a seventh-grade pill and saved Tang Huoer