golangロングとショートの接続接続の学習

  • TCPの接続図

  • ロングとショートの接続リンクとの違い
    • クライアントとサーバーの応答の数
      • ロング接続:複数回。
      • ショートリンク:。
    • ウェイデータ伝送
      • ロング接続:接続 - データ転送は - 接続されたまま
      • ショート接続:接続 - データ転送 - 接続を閉じます
  • ロングとショートの接続リンクの長所と短所

    • ロング接続
      • 利点
        • これにより、時間を節約し、より多くのTCP及び決算業務を確立する必要がなくなります。
        • パフォーマンスが優れています。(クライアントとサーバが連絡を取り合う必要があるため)
      • 短所
        • サーバは圧倒され、より多くのクライアントとして。
        • 接続管理が難しいです。
        • 悪いのセキュリティ。(それは、接続を維持するように、ランダムデータを送信する、などのいくつかの悪質なクライアントがあるかもしれません)
    • ショートリンク
      • 利点
        • シンプルなサービス管理。接続は、本リンクされています
      • 短所
        • TCPオペレーションの確立と終了の時間を無駄に頻繁に要求、
  • 長い接続と短い接続の使用例

    • ロング接続
      • マイクロチャネル/ QQ
      • いくつかのゲーム
    • ショート接続
      • 通常のウェブサイト
  • golang長い接続参照コード(実施グループチャット)を達成

    server.go

package main

import(
    "fmt"
    "net"
    "bufio"
    "errors"
)
var connSlice []*net.TCPConn

// 创建TCP长连接服务
func createTcp(){
    tcpAdd,err:= net.ResolveTCPAddr("tcp","127.0.0.1:9999")  //解析tcp服务
    if err!=nil{
        fmt.Println("net.ResolveTCPAddr error:",err)
        return
    }
    tcpListener,err:=net.ListenTCP("tcp",tcpAdd)   //监听指定TCP服务
    if err!=nil{
        fmt.Println("net.ListenTCP error:",err)
        return
    }
    defer tcpListener.Close()
    for{
        tcpConn,err:=tcpListener.AcceptTCP() //阻塞,当有客户端连接时,才会运行下面
        if err!=nil{
            fmt.Println("tcpListener error :",err)
            continue
        }
        fmt.Println("A client connected:",tcpConn.RemoteAddr().String())
        boradcastMessage(tcpConn.RemoteAddr().String()+"进入房间"+"\n")  //当有一个客户端进来之时,广播某某进入房间
        connSlice = append(connSlice,tcpConn)
        // 监听到被访问时,开一个协程处理
        go tcpPipe(tcpConn)
    }
}

// 对客户端作出反应
func tcpPipe(conn *net.TCPConn){
    ipStr := conn.RemoteAddr().String()
    fmt.Println("ipStr:",ipStr)
    defer func(){
        fmt.Println("disconnected:",ipStr)
        conn.Close()
        deleteConn(conn)
        boradcastMessage(ipStr+"离开了房间"+"\n")
    }()
    reader:=bufio.NewReader(conn)
    for{
        message,err:=reader.ReadString('\n')  //读取直到输入中第一次发生 ‘\n’
        //因为按强制退出的时候,他就先发送换行,然后在结束
        if message == "\n"{
            return
        }
        message = ipStr+"说:"+message
        if err!=nil{
            fmt.Println("topPipe:",err)
            return
        }
        // 广播消息
        fmt.Println(ipStr,"说:",message)
        err = boradcastMessage(message)
        if err!=nil{
            fmt.Println(err)
            return 
        }
    }
}

// 广播数据
func boradcastMessage(message string)error{
    b := []byte(message)
    for i:=0;i<len(connSlice);i++{
        fmt.Println(connSlice[i])
        _,err := connSlice[i].Write(b)
        if err!=nil{
            fmt.Println("发送给",connSlice[i].RemoteAddr().String(),"数据失败"+err.Error())
            continue
        }
    }
    return nil
}

// 移除已经关闭的客户端
func deleteConn(conn *net.TCPConn)error{
    if conn==nil{
        fmt.Println("conn is nil")
        return errors.New("conn is nil")
    }
    for i:= 0;i<len(connSlice);i++{
        if(connSlice[i]==conn){
            connSlice = append(connSlice[:i],connSlice[i+1:]...)
            break
        }
    }
    return nil
}

func main(){
    fmt.Println("服务端")
    createTcp()
    // data := []string{"a","b"}
    // data = append(data[:1],data[2:]...)  //测试data[2:]...会不会因为超过范围报错
    // fmt.Println(data)
}
**client.go**
package main

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


// 客户端连接服务端
func createSocket(){
    tcpAdd,err := net.ResolveTCPAddr("tcp","127.0.0.1:9999")  //解析服务端TCP地址
    if err!=nil{
        fmt.Println("net.ResolveTCPAddr error:",err)
        return
    }
    conn,err := net.DialTCP("tcp",nil,tcpAdd)   //raddr是指远程地址,laddr是指本地地址,连接服务端
    if err!=nil{
        fmt.Println("net.DailTCP error:",err)
        return
    }
    defer conn.Close()
    fmt.Println("connected")
    go onMessageRectived(conn)   //读取服务端广播的信息

    for {
        // 自己发送的信息
        var data string
        fmt.Scan(&data)
        if data == "quit"{
            break
        }
        b := []byte(data + "\n")
        conn.Write(b)
    }
}

// 获取服务端发送来的信息
func onMessageRectived(conn *net.TCPConn){
    reader := bufio.NewReader(conn)
    for {
        // var data string
        msg,err := reader.ReadString('\n')  //读取直到输入中第一次发生 ‘\n’
        fmt.Println(msg)
        if err!=nil{
            fmt.Println("err:",err)
            os.Exit(1)    //服务端错误的时候,就将整个客户端关掉
        }   
    }
}

func main(){
    fmt.Println("开启客户端")
    createSocket()
}
  • golang短い接続参照コードを達成

    server.go

package main

import (
    "fmt"
    "net/http"
)

func main(){
    fmt.Println("服务端")
    http.HandleFunc("/PrintHello",PrintHello)
    http.ListenAndServe(":8080",nil)
}

func PrintHello(w http.ResponseWriter,r *http.Request){
    data := "hello word"
    fmt.Fprintf(w,data)
}

client.go

package main

import(
    "fmt"
    "net/http"
    "io/ioutil"
)

func main(){
    fmt.Println("客户端")
    res,err:=http.Get("http://localhost:8080/PrintHello")
    if err!=nil{
        fmt.Println(err)
        return
    }
    defer res.Body.Close()
    data,err := ioutil.ReadAll(res.Body)
    if err!=nil{
        fmt.Println(err)
        return
    }
    fmt.Println("接受服务端发送数据:",string(data))
}
  • さらに、長い接続のgolangクライアントの実装は、サーバーへの接続後に接続を確立することにより維持されています

  • マイクロチャネルを議論するために追加することを望んで、書くために間違った場所

おすすめ

転載: www.cnblogs.com/MyUniverse/p/11621169.html