golang长连接和短连接的学习

  • TCP连接示意图

  • 长连接和短链接的区别

    • 客户端和服务端响应的次数

      • 长连接:可以多次。
      • 短链接:一次。
    • 传输数据的方式
      • 长连接:连接--数据传输--保持连接
      • 短连接:连接--数据传输--关闭连接
  • 长连接和短链接的优缺点
    • 长连接

      • 优点

        • 省去较多的TCP建立和关闭的操作,从而节约时间。
        • 性能比较好。(因为客户端一直和服务端保持联系)
      • 缺点
        • 当客户端越来越多的时候,会让将服务器压垮。
        • 连接管理难。
        • 安全性差。(因为会一直保持着连接,可能会有些无良的客户端,随意发送数据等)
    • 短链接
      • 优点

        • 服务管理简单。存在的连接都是有效连接
      • 缺点
        • 请求频繁,在TCP的建立和关闭操作上浪费时间
  • 长连接和短连接使用情况举例
    • 长连接

      • 微信/qq
      • 一些游戏
    • 短连接
      • 普通的web网站
  • 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的client实现长连接的方式是通过于服务端在建立连接之后保持连接
  • 写的不对的地方,希望可以加微信讨论一下

原文地址:https://www.cnblogs.com/MyUniverse/p/11621169.html

时间: 2024-10-28 16:06:42

golang长连接和短连接的学习的相关文章

HTTP的长连接和短连接——Node上的测试

    本文主要从实践角度介绍长.短连接在TCP层面的表现,借助Node.JS搭建后台服务,使用WinHTTP.Ajax做客户端请求测试,最后简单涉及WebSocket.     关键字:长连接.短连接.Node.JS.WebSocket. 一两年前,在理论上对长短连接做了学习,那时的技能以客户端为主,所以也止步于客户端和网络抓包,两年来后台技术渐有把握,打算从前到后的实践一遍.如对理论有不理解的,可以先google/百度 一下,或者看看这篇偏理论的介绍:HTTP的长连接和短连接. 1 短连接的

[转]HTTP的长连接和短连接

本文原链接:http://www.cnblogs.com/cswuyg/p/3653263.html   本文总结&分享网络编程中涉及的长连接.短连接概念.     关键字:Keep-Alive,并发连接数限制,TCP,HTTP 一.什么是长连接 HTTP1.1规定了默认保持长连接(HTTP persistent connection ,也有翻译为持久连接),数据传输完成了保持TCP连接不断开(不发RST包.不四次握手),等待在同域名下继续用这个通道传输数据:相反的就是短连接. HTTP首部的C

HTTP的长连接和短连接

 http://www.cnblogs.com/cswuyg/p/3653263.html 本文总结&分享网络编程中涉及的长连接.短连接概念.     关键字:Keep-Alive,并发连接数限制,TCP,HTTP 一.什么是长连接 HTTP1.1规定了默认保持长连接(HTTP persistent connection ,也有翻译为持久连接),数据传输完成了保持TCP连接不断开(不发RST包.不四次握手),等待在同域名下继续用这个通道传输数据:相反的就是短连接. HTTP首部的Connecti

[转载] http长连接和短连接

转载自http://blog.csdn.net/shine0181/article/details/7799754/ HTTP实现长连接 HTTP是无状态的 也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接.如果客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源,如JavaScript文件.图像文件.CSS文件等:当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话 HTTP1.1和HTTP1.0相比较而言,最大的区别就是增加了持

TCP中的长连接和短连接(转载)

原文地址:http://www.cnblogs.com/onlysun/p/4520553.html 当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次握手的,而释放则需要4次挥手,所以说每个连接的建立都是需要资源消耗和时间消耗的 示意图: 长连接: 所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以

【HTTP】长连接和短连接

1. HTTP协议与TCP/IP协议的关系 HTTP的长连接和短连接本质上是TCP长连接和短连接.HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议.IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠的传递数据包,使在网络上的另一端收到发端发出的所有包,并且顺序与发出顺序一致.TCP有可靠,面向连接的特点. 2. 如何理解HTTP协议是无状态的 HTTP协议是无状态的,指的是协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态.也就是说,打开一个服

HTTP长连接和短连接

1.HTTP协议的五大特点1)支持客户/服务器模式2)简单快速3)灵活4)无连接每次连接只处理一个请求,服务器处理完客户的请求,并受到客户的应答后,断开连接.5)无状态协议不会记录服务器客户端状态. 2.保持HTTP连接状态的两种方式1)Cookie在访问统一网站时,可以将信息写入cookie,方便在不同的页面间提取信息. 2)SessionSession保存在服务器上,同时将标识Session的SessionId传递给客户端浏览器,保存在cookie中,浏览器关闭后,这个cookie就会被清掉

HTTP 长连接和短连接

1. HTTP协议与TCP/IP协议的关系 HTTP的长连接和短连接本质上是TCP长连接和短连接.HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议.IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠的传递数据包,使在网络上的另一端收到发端发出的所有包,并且顺序与发出顺序一致.TCP有可靠,面向连接的特点. 2. 如何理解HTTP协议是无状态的 HTTP协议是无状态的,指的是协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态.也就是说,打开一个服

TCP/IP系列——长连接与短连接的区别

1 什么是长连接和短连接 三次握手和四次挥手 TCP区别于UDP最重要的特点是TCP必须建立在可靠的连接之上,连接的建立和释放就是握手和挥手的过程. 三次握手为连接的建立过程,握手失败则连接建立失败. 四次挥手为连接的完整释放过程,也会发生某个消息丢失或者超时的情况,有一方主动发送FIN消息即表示连接即将释放. 注:SYN.ACK.FIN消息具有哪些含义,以及连接的状态,请参考<TCP/IP详解 卷1>第18章. 长连接 长连接,也叫持久连接,在TCP层握手成功后,不立即断开连接,并在此连接的