從零開始學golang之TCP

freedbg發表於2018-03-11
package main

import (
    "flag"
    "fmt"
    "net"
    "os"
    "time"
)

/**
 *  tcp 啟動 連結 三次握手  關閉四次
 *  慢啟動 + 擁塞視窗
 *  門限控制 < 擁塞視窗 進入擁塞避免
 *  在傳送資料後 檢測 ack 確認超時 或者 收到重複ack 確認 操作門限值 和 擁塞視窗值 來限流
 *  接收方 使用通告視窗 告知傳送可接受多少位元組
 *
 *  傳送方:滑動視窗協議
 */

//結構體內嵌介面
type Man struct {
    iTest
    name string
}

type iTest interface {
    hello()
}

type Em struct {
    good string
}

func (em *Em) hello() {
    fmt.Println(em.good)
}

func (man *Man) hello() {
    fmt.Println(man.name)
}

var workerChan = make(chan *net.TCPConn, 10000)
var graddr *string

func main() {

    // vman := Man{
    //  &Em{
    //      good: "goodman",
    //  },
    //  "helloman"}
    // vman.hello()
    // fmt.Println(vman)

    nf := flag.String("name", "server", "input server or client")
    graddr = flag.String("ip", "127.0.0.1:999", "ip:port")
    flag.Parse()
    fmt.Println(*nf)
    if *nf == "server" {
        server()
    } else {
        client()
    }

    var wait string
    fmt.Scanln(&wait)
}

func server() {
    laddr, aerr := net.ResolveTCPAddr("tcp", ":999")
    if aerr != nil {
        os.Exit(1)
    }
    listen, lerr := net.ListenTCP("tcp", laddr)
    defer listen.Close()
    if lerr != nil {
        os.Exit(2)
    }

    //plan2 code start
    for i := 0; i < 10; i++ {
        go sworker2(workerChan)
    }

    st := time.Now()
    var cn int
    cn = 0
    //plan2 code end
    for {

        tcpConn, cerr := listen.AcceptTCP()
        if cerr == nil {
            cn++
            //go sworker(tcpConn) //plan 1
            workerChan <- tcpConn //plan 2 減少了工作協程建立
        }
        if time.Since(st).Seconds() >= 2 {
            fmt.Println("accept tcp client :", cn)
            cn = 0
            st = time.Now()
        }
    }
}

/**
 * 通過chan,的工作執行緒
 */
func sworker2(conns <-chan *net.TCPConn) {
    fmt.Println("sworker2")
    var b [1500]byte
    for conn := range conns {
        //for {
        _, err := conn.Read(b[0:])

        if err == nil {
            //fmt.Println(string(b[0:len]))
        }

        conn.Write([]byte("HELLO WORLD"))
        //conn.Close()
        //}
    }
}

/**
 * 工作協程
 */
func sworker(conn *net.TCPConn) {
    fmt.Println("sworker")
    var b [1500]byte
    for {
        len, err := conn.Read(b[0:])

        if err == nil {
            fmt.Println(string(b[0:len]))
        }

        conn.Write([]byte("HELLO WORLD"))
    }
}

func client() {
    //linux 預設檔案數開啟1024
    //ulimit -n 50000 修改
    for i := 0; i < 40000; i++ {
        fmt.Println("create clint", i)
        go func() {
            defer func() {
                if err := recover(); err != nil {
                    fmt.Println(err)
                }
            }()
            raddr, rerr := net.ResolveTCPAddr("tcp", *graddr)
            if rerr != nil {
                fmt.Println(rerr)
                return
                //os.Exit(3)
            }
            tcpConn, dterr := net.DialTCP("tcp", nil, raddr)

            if dterr != nil {
                fmt.Println(dterr)
                return
            }

            var b [1500]byte

            wlen, err := tcpConn.Write([]byte("ARE-U-THERE"))
            if err == nil && wlen > 0 {
                tcpConn.Read(b[0:])
                //fmt.Println(string(b[0:rlen]))
            } else {
                fmt.Println(err)
            }
        }()
    }
}

所有程式碼地址:https://github.com/godla/TCP-IP-Study

更多原創文章乾貨分享,請關注公眾號
  • 從零開始學golang之TCP
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章