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相关推荐

  1. Golang源码阅读笔记 - String

    String用法说明 在src/buildin/buildin.go文件中,对golang内建数据类型做了详细的描述,关于string的说明如下: // string is the set of al ...

  2. 【Golang源码阅读】builtin/builtin.go

    // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a B ...

  3. 【Golang源码阅读】strings/builder.go

    // Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a B ...

  4. Golang流媒体实战之五:lal推流服务源码阅读

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos <Golang流媒体实战>系列的链接 体验 ...

  5. Golang流媒体实战之六:lal拉流服务源码阅读

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos <Golang流媒体实战>系列的链接 体验 ...

  6. golang源码解读之 net.Dial

    1.调用 例子 conn, err := net.Dial("tcp", "google.com:80") if err != nil {// handle e ...

  7. android tcp socket框架_最流行的 Web 框架 Gin 源码阅读

    最近公司大部分项目开始往golang换, api的框架选定使用gin, 于是将 gin的源码看了一遍, 会用几篇文章将gin的流程及流程做一个梳理, 下面进入正题. gin框架预览 上图大概是 gin ...

  8. logrus 输出多个文件_Logrus源码阅读(1)基本用法

    选择golang日志库时, 使用logrus的主要原因就是因为star比较多, 而且社区活跃度非常高. 在项目使用过程中, 发现logrus的调用入口, 性能, 插件, 自定义插件, 输出格式等都非常 ...

  9. strings.Builder 源码阅读与分析

    strings.Builder源码阅读与分析 背景之字符串拼接 在 Go 语言中,对于字符串的拼接处理有很多种方法,那么那种方法才是效率最高的呢? str := []string{"aa&q ...

最新文章

  1. Java 未死,依然很牛逼!
  2. linux通过rinetd工具进行端口映射/转发/重定向
  3. java多线程3.设计线程安全类
  4. ubuntu 环境下调试mysql源码_【转】Ubuntu 16.04下 Mysql 5.7.17源码编译与安装
  5. AdminLTE基本使用介绍
  6. 资料分享 | 数学建模竞赛备战大全
  7. 我理解的Future模式
  8. web安全day38:使用Vulhub一键搭建测试靶场
  9. 《数学建模与数学实验》第1章学习笔记
  10. 类型函数(type function)
  11. 【转载】:马家寨:揭开陈圆圆携吴三桂后裔隐藏与繁衍真相
  12. [paper]DeepFool: a simple and accurate method to fool deep neural networks
  13. 优秀logo设计解析_国外30个优秀的logo的设计思维分析
  14. [18调剂]上海海洋大学2018年硕士研究生调剂政策与规则
  15. not discrete but [0, 1]. Specify a discrete sample time in
  16. 系统测试常用测试方法
  17. jstree 新建node后,刷新jstree的改变的那一部分
  18. 500以内的蓝牙降噪耳机哪款好?高性价比降噪蓝牙耳机分享
  19. SEO、SSR、Nuxt.js
  20. 数字集成电路版图设计(附录)——持续补充...

热门文章

  1. 信息论(熵、条件熵、联合熵、互信息)
  2. 源码:FastReport FMX 2022.1
  3. Maven 项目打war包步骤
  4. MATLAB简单图形绘制——小蝴蝶
  5. 自媒体如何拥有多个头条号
  6. arduino编码器计数_几根线做的Arduino液晶屏旋转编码器带你进入数字化编程之旅...
  7. Keil5----新建项目文件( .c文件 和 .h文件)
  8. 移远EC200T 4G LTE模块在MDK9X25L-EK(AT91SAM9X25)平台的应用演示
  9. no matching manifest for windows/amd64 10.0.18362 in the manifest list entries
  10. 求两个List的交集和并集