Go语言net包

本文介绍了Go语言中的net包,包括Listen()、Accept()、Read()/Write()的底层逻辑,并探讨了如何结合阻塞模型与多路复用来优化网络服务。通过Listen()创建TCPListener,Accept()接收新连接并转化为TCPConn,而Read()/Write()负责数据的读写。文章指出,使用主协程监听新连接并在有新连接时启动新协程服务是避免阻塞的有效策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、net

net包抽象了TCP网络操作,使用listen()得到处于listen状态的TCPListener,使用Accept()得到处于established状态的TCPConn,使用Read()/Write()进行读写socket的操作。

1.Listen()

package main

import (
    "net"
    "fmt"
)

func main() {
    listener, err := net.Listen("tcp", "8888")
    if err != nil {
        fmt.Println(err)
    }
}

net.Listen()的底层逻辑:

  • 新建socket,并执行bind操作,上述代码,将socket绑定到8888端口上。
  • 新建一个FD,这是net包对socket的详情描述。
  • 返回一个TCPListener对象,将TCPListener的FD信息加入监听。
  • TCPListener对象的本质是一个listen状态的socket。
  • 此时这个socket已经被加入到系统底层的多路复用器中了。

2.Accept()

package main

import (
    "net"
    "fmt"
)

func main() {
    listener, err := net.Listen("tcp", "8888")
    if err != nil {
        fmt.Println(err)
    }
    conn, err := listener.Accept()
    if err != nil {
        fmt.Println(err)
    }
}

Accept()的底层逻辑:

  • 直接调用socket的accept(),如果失败,休眠等待新连接。
  • 将新的socket包装为TCPConn变量返回。
  • 将TCPConn的FD信息加入监听。
  • TCPConn本质上是一个处于established状态的socket。

3.Read()/wirte()

package main

import (
    "net"
    "fmt"
)

func main() {
    listener, err := net.Listen("tcp", "8888")
    if err != nil {
        fmt.Println(err)
    }

    conn, err := listener.Accept()
    if err != nil {
        fmt.Println(err)
    }

    var buf [1024]byte
    for {
        _, err := conn.Read(buf[:])
        if err != nil {
            break
        }
        fmt.Printf("%s", string(buf[:]))
        
        _, err := conn.Write(buf[:])
        if err != nil {
            break
        }
    }
}

Read()/wirte()底层逻辑:

  • 调用socket原生读写方法,如果失败,休眠等待可读/可写。
  • 被唤醒后调用系统socket。

但是上述代码是有问题的,就是我们使用主协程监听新连接,并且用主协程来服务这个新连接。

4.结合阻塞模型与多路复用

思路:用主协程监听新连接,每当有新连接到来时,就开启一个协程为其服务。

package main

import (
    "net"
    "fmt"
)

func handleConnection(conn net.Conn) {
    defer conn.Close()
    var buf [1024]byte

    for {
        _, err := conn.Read(buf[:])
        if err != nil {
            break
        }
        fmt.Printf("%s", string(buf[:]))
        
        _, err := conn.Write(buf[:])
        if err != nil {
            break
        }
    }
}

func main() {
    listener, err := net.Listen("tcp", "8888")
    if err != nil {
        fmt.Println(err)
    }

    for {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Println(err)
        }
        go handleConnection(conn)  
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值