可靠数据传输的基础

气道正压通气


那些寻求了解网络和协议的人是专门的。


简要地

, Go, UDP TCP. , , " . ", .


传输层协议


在不同主机上运行的应用程序进程之间提供逻辑连接。从应用程序的角度来看,逻辑连接看起来像是直接连接进程的通道。



, ( — DPI). , , , .



( ) .



, () . . , -.





. , .


package main

import (
    "log"
    "net"
)

func main() {
    // IP-   
    serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:12000")
    if err != nil {
        log.Fatal(err)
    }

    //    
    serverConn, err := net.ListenUDP("udp", serverAddr)
    if err != nil {
        log.Fatal(err)
    }
    //   
    defer serverConn.Close()

    //    
    buf := make([]byte, 1024)

    //  
    for {
        //  
        n, addr, err := serverConn.ReadFromUDP(buf)
        //     :    stdout
        println(string(buf[0:n]), " form ", addr.IP.String())
        if err != nil {
            log.Fatal(err)
        }
        //  , ..  UDP +  
    }
}

package main

import (
    "fmt"
    "log"
    "net"
    "time"
)

func main() {
    // IP-   
    serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:12000")
    if err != nil {
        log.Fatal(err)
    }
    //  IP-  
    localAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
    if err != nil {
        log.Fatal(err)
    }
    //  
    conn, err := net.DialUDP("udp", localAddr, serverAddr)
    if err != nil {
        log.Fatal(err)
    }
    //   
    defer conn.Close()

    for {
        //     
        fmt.Print("   > ")
        var msg string
        _, err := fmt.Scanf("%s", &msg)
        if err != nil {
            log.Fatal(err)
        }
        //   ,   
        buf := []byte(msg)
        //  ()  
        _, err = conn.Write(buf)
        if err != nil {
            log.Fatal(err)
        }
        // 1 
        time.Sleep(time.Second * 1)
    }
}


— , , , , , .



:


  • ;
  • ;
  • .

, , (Automatic Repeat reQuest, ARQ).
, , .
, TCP, , .



,


, , .
:


  • ;
  • .

, , , , . : . , . net TCPKeepAlive 15 :


// defaultTCPKeepAlive is a default constant value for TCPKeepAlive times
// See golang.org/issue/31510
const (
    defaultTCPKeepAlive = 15 * time.Second
)

( , ), .


, :


  • ;
  • ;
  • ;
  • .

!



, , . «» , , RTT. , .



:


  • , ( ) ;
  • .

, , . :


  • N ;
  • .

N —



:


  • . «» , ( N , ). , , . , , . . , , ( ), (, ), .
  • . N , , , N, .
  • . . , .


, . , .



TCP. - , — welcome.


package main

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "strings"
)

func main() {
    //     
    ln, err := net.Listen("tcp", ":8081")
    if err != nil {
        log.Fatalln(err)
    }
    //  
    conn, _ := ln.Accept()

    for {
        //  
        msg, err := bufio.NewReader(conn).ReadString('\n')
        if err != nil {
            log.Fatalln(err)
        }
        //    stdout
        fmt.Print("Message Received:", string(msg))
        //     
        newMsg := strings.ToUpper(msg)
        //  
        conn.Write([]byte(newMsg + "\n"))
    }
}

package main

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "os"
)

func main() {
    //  
    conn, err := net.Dial("tcp", "127.0.0.1:8081")
    if err != nil {
        log.Fatalln(err)
    }

    for {
        //    stdin
        reader := bufio.NewReader(os.Stdin)
        fmt.Print("Text to send: ")
        // 
        text, err := reader.ReadString('\n')
        if err != nil {
            log.Fatalln(err)
        }
        // 
        fmt.Fprintf(conn, text+"\n")
        // 
        msg, err := bufio.NewReader(conn).ReadString('\n')
        if err != nil {
            log.Fatalln(err)
        }
        //   
        fmt.Print("Msg from Server: " + msg)
    }
}


,


,
. , . , , ( ), ,
. . ,
, . .
, . ,
,限制可用于传输数据包的序列号的范围。与确认待机模式相比,多播和握手可以显着提高协议吞吐量。正如我们将看到的,可以根据接收方的接收和缓冲能力以及网络负载水平来计算窗口大小

使用Go进行联网的其他示例


资源库中


All Articles