Go语言网络模型

在底层使用操作系统的多路复用IO,在协程使用阻塞模型。

epoll抽象层用于抽象linux,windows,mac下的网络多路复用。

netpollinit()->epoll_create()。新建epoll,拿到文件描述符,新建一个pipe用于中断epoll,有管道数据到达事件注册到epoll中。

epoll_ctl()->netpollopen()(监听事件)。传入socket的fd, pollDesc指针,pollDesc指针是socket相关详细信息,pollDesc指针记录了哪个 协程休眠等待这个socket,将socket可读可写断开事件注册到epoll中

epoll_wait()->netpoll()。(查询哪些事件发生),根据socket相关的pollDesc信息返回哪些协程可以唤醒的列表

go network Poller用于多路复用的抽象和适配。更上一层。

poll_runtime_pollServerInit(),调用netpollinit()但使用原子操作保证只初始化一次。

pollCache struct {}带锁的链表头

PollDesc struct {}链表成员,是Socket的详细描述(rg,wg 等待协程的地址)

poll_runtime_pollOpen()在pollCache链表中分配一个pollDesc,初始化pollDesc(用于监听Socket),调用netpollopen()。

gcStart调用netpoll()。因为垃圾回收循环查询(G0协程),于是在这放了个netpoll()钩子可以循环调用。场景1:发现Socket可以读写,则对应的rg 或者wg设置为 1。协程调用poll_runtime_pollWait()判断rg 或 wg是否为1.

场景2:协程调用poll_runtime_pollWait()后发现g 或 wg为0则给对应的g 或 wg设置为协程地址,休眠等待。当netpoll发现socket可读写时,查看对应的g 或 wg,若为协程地址则返回协程地址,调度器开始调度这个协程。

GO是如何抽象socket?是net包

net包实现TCP UDP HTTP。

net.listen()新建Socket,并执行bind操作。新建一个FD(net包对socket的描述)返回TCP listener对象。将TCP listener的FD加入监听。TCP listener本质是一个listen状态的Socket。所以这方法我们完成下图第一步新建socket并加入监听:

TCP Listener.Accept()直接调用Socket的accept(),如果失败则休眠等待。成功,将生成新的socket包装成TCPConn变量返回,将TCPConn的FD信息加入监听。TCPConn本质上是一个ESTABLISHED状态的Socket。至此完成第二步

TCPConn.Read()/Write()直接调用Socket原生读写方法,如果失败,休眠等待可读可写,被唤醒后调用系统Socket。

net包是直接操作socket的如果操作不了,则把自己记录在pollDesc中。

go-per-connection编程风格:一个协程一个连接。主协程监听listener,每个conn使用一个新协程处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值