golang源码阅读-net.Dial
1.基本使用
//获取链接
conn, err := net.Dial("tcp", "0.0.0.0:8080")if err != nil {fmt.Println("Dial error ", err)return}//通过链接写入数据conn.Write([]byte("hello everyone"))
2.Dial源码
func Dial(network, address string) (Conn, error) {var d Dialer
//调用Dialer的Dial方法return d.Dial(network, address)
}
3.Dialer的Dial方法源码
func (d *Dialer) Dial(network, address string) (Conn, error) {return d.DialContext(context.Background(), network, address)
}
4. DialContext源码
func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn, error) {
//判断上下文是否为空if ctx == nil {panic("nil context")}
//获取deadline, 获取dialer和上下文的最早的deadlinedeadline := d.deadline(ctx, time.Now())if !deadline.IsZero() {
//如果不是日期的 0//如果上下文没有deadline 或者 上下文的deadline早于dialer的if d, ok := ctx.Deadline(); !ok || deadline.Before(d) {//构建子上下文subCtx, cancel := context.WithDeadline(ctx, deadline)defer cancel()ctx = subCtx}}
//如果dialer有cancel 转成上下文 WithCancelif oldCancel := d.Cancel; oldCancel != nil {subCtx, cancel := context.WithCancel(ctx)defer cancel()go func() {select {case <-oldCancel:cancel()case <-subCtx.Done():}}()ctx = subCtx}// Shadow the nettrace (if any) during resolve so Connect events don't fire for DNS lookups.resolveCtx := ctxif trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace); trace != nil {shadow := *traceshadow.ConnectStart = nilshadow.ConnectDone = nilresolveCtx = context.WithValue(resolveCtx, nettrace.TraceKey{}, &shadow)}//解析出地址列表addrs, err := d.resolver().resolveAddrList(resolveCtx, "dial", network, address, d.LocalAddr)if err != nil {return nil, &OpError{Op: "dial", Net: network, Source: nil, Addr: nil, Err: err}}//实例sd := &sysDialer{Dialer: *d,network: network,address: address,}//ipv6回退ipv4的处理var primaries, fallbacks addrListif d.dualStack() && network == "tcp" {primaries, fallbacks = addrs.partition(isIPv4)} else {primaries = addrs}var c Connif len(fallbacks) > 0 {c, err = sd.dialParallel(ctx, primaries, fallbacks)} else {//获取链接c, err = sd.dialSerial(ctx, primaries)}if err != nil {return nil, err}//如果是tcp链接 设置 KeepAliveif tc, ok := c.(*TCPConn); ok && d.KeepAlive >= 0 {setKeepAlive(tc.fd, true)ka := d.KeepAliveif d.KeepAlive == 0 {ka = 15 * time.Second}setKeepAlivePeriod(tc.fd, ka)testHookSetKeepAlive(ka)}return c, nil
}
5.sd.dialSerial源码
func (sd *sysDialer) dialSerial(ctx context.Context, ras addrList) (Conn, error) {//链接的第一个错误
var firstErr error // The error from the first address is most relevant.//遍历地址for i, ra := range ras {//上下文 是否取消select {case <-ctx.Done():return nil, &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: mapErr(ctx.Err())}default:}//上下文的deadlinedeadline, _ := ctx.Deadline()//处理deadlinepartialDeadline, err := partialDeadline(time.Now(), deadline, len(ras)-i)if err != nil {// Ran out of time.if firstErr == nil {firstErr = &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: err}}break}dialCtx := ctx//处理后deadline 早于上下文的deadlineif partialDeadline.Before(deadline) {var cancel context.CancelFunc//新的WithDeadlinedialCtx, cancel = context.WithDeadline(ctx, partialDeadline)defer cancel()}//链接一个地址c, err := sd.dialSingle(dialCtx, ra)//如果成功直接返回if err == nil {return c, nil}if firstErr == nil {firstErr = err}}if firstErr == nil {firstErr = &OpError{Op: "dial", Net: sd.network, Source: nil, Addr: nil, Err: errMissingAddress}}return nil, firstErr
}
6.处理deadlien 的方法 partialDeadline源码
func partialDeadline(now, deadline time.Time, addrsRemaining int) (time.Time, error) {
//如果时间是0if deadline.IsZero() {return deadline, nil}
//deadline和当前时间的间距timeRemaining := deadline.Sub(now)if timeRemaining <= 0 {return time.Time{}, poll.ErrTimeout}// Tentatively allocate equal time to each remaining address.//时间间距除以 i(第几个地址) timeout := timeRemaining / time.Duration(addrsRemaining)// If the time per address is too short, steal from the end of the list.//2秒
const saneMinimum = 2 * time.Second
//小于2if timeout < saneMinimum {//总的deadlien小于2if timeRemaining < saneMinimum {timeout = timeRemaining} else {//一个链接的超时等于2timeout = saneMinimum}}return now.Add(timeout), nil
}
golang源码阅读-net.Dial相关推荐
- Golang源码阅读笔记 - String
String用法说明 在src/buildin/buildin.go文件中,对golang内建数据类型做了详细的描述,关于string的说明如下: // string is the set of al ...
- 【Golang源码阅读】builtin/builtin.go
// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a B ...
- 【Golang源码阅读】strings/builder.go
// Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a B ...
- Golang流媒体实战之五:lal推流服务源码阅读
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos <Golang流媒体实战>系列的链接 体验 ...
- Golang流媒体实战之六:lal拉流服务源码阅读
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos <Golang流媒体实战>系列的链接 体验 ...
- golang源码解读之 net.Dial
1.调用 例子 conn, err := net.Dial("tcp", "google.com:80") if err != nil {// handle e ...
- android tcp socket框架_最流行的 Web 框架 Gin 源码阅读
最近公司大部分项目开始往golang换, api的框架选定使用gin, 于是将 gin的源码看了一遍, 会用几篇文章将gin的流程及流程做一个梳理, 下面进入正题. gin框架预览 上图大概是 gin ...
- logrus 输出多个文件_Logrus源码阅读(1)基本用法
选择golang日志库时, 使用logrus的主要原因就是因为star比较多, 而且社区活跃度非常高. 在项目使用过程中, 发现logrus的调用入口, 性能, 插件, 自定义插件, 输出格式等都非常 ...
- strings.Builder 源码阅读与分析
strings.Builder源码阅读与分析 背景之字符串拼接 在 Go 语言中,对于字符串的拼接处理有很多种方法,那么那种方法才是效率最高的呢? str := []string{"aa&q ...
最新文章
- Java 未死,依然很牛逼!
- linux通过rinetd工具进行端口映射/转发/重定向
- java多线程3.设计线程安全类
- ubuntu 环境下调试mysql源码_【转】Ubuntu 16.04下 Mysql 5.7.17源码编译与安装
- AdminLTE基本使用介绍
- 资料分享 | 数学建模竞赛备战大全
- 我理解的Future模式
- web安全day38:使用Vulhub一键搭建测试靶场
- 《数学建模与数学实验》第1章学习笔记
- 类型函数(type function)
- 【转载】:马家寨:揭开陈圆圆携吴三桂后裔隐藏与繁衍真相
- [paper]DeepFool: a simple and accurate method to fool deep neural networks
- 优秀logo设计解析_国外30个优秀的logo的设计思维分析
- [18调剂]上海海洋大学2018年硕士研究生调剂政策与规则
- not discrete but [0, 1]. Specify a discrete sample time in
- 系统测试常用测试方法
- jstree 新建node后,刷新jstree的改变的那一部分
- 500以内的蓝牙降噪耳机哪款好?高性价比降噪蓝牙耳机分享
- SEO、SSR、Nuxt.js
- 数字集成电路版图设计(附录)——持续补充...
热门文章
- 信息论(熵、条件熵、联合熵、互信息)
- 源码:FastReport FMX 2022.1
- Maven 项目打war包步骤
- MATLAB简单图形绘制——小蝴蝶
- 自媒体如何拥有多个头条号
- arduino编码器计数_几根线做的Arduino液晶屏旋转编码器带你进入数字化编程之旅...
- Keil5----新建项目文件( .c文件 和 .h文件)
- 移远EC200T 4G LTE模块在MDK9X25L-EK(AT91SAM9X25)平台的应用演示
- no matching manifest for windows/amd64 10.0.18362 in the manifest list entries
- 求两个List的交集和并集