教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 Golang 网络编程丝绸之路 - TCP/UDP 地址解析

Golang 网络编程丝绸之路 - TCP/UDP 地址解析

发布时间:2021-12-26   编辑:jiaochengji.com
教程集为您提供Golang 网络编程丝绸之路 - TCP/UDP 地址解析等资源,欢迎您收藏本站,我们将为您提供最新的Golang 网络编程丝绸之路 - TCP/UDP 地址解析资源

TL;DR 在使用 Golang 编写 TCP/UDP socket 的时候,第一步做的就是地址解析。

<ul><li>func ResolveTCPAddr(network, address string) (*TCPAddr, error)</li> <li> func ResolveUDPAddr(network, address string) (*UDPAddr, error)
下面是对这两个函数的源码分析。</li> </ul><h2>ResolveTCPAddr</h2>

该函数返回的地址包含的信息如下:

<pre><code class="lang-go hljs">// src/net/tcpsock.go type TCPAddr struct { IP IP Port int Zone string // IPv6 scoped addressing zone } </code></code></pre>

TCPAddr 里,<code>IP</code> 既可以是 IPv4 地址,也可以是 IPv6 地址。<code>Port</code> 就是端口了。<code>Zone</code> 是 IPv6 本地地址所在的区域。
从返回结果看该函数的参数,<code>network</code> 指 <code>address</code> 的网络类型;<code>address</code> 指要解析的地址,会从中解析出我们想要的 <code>IP</code>, <code>Port</code> 和 <code>Zone</code>。

<h3>源码分析</h3> <pre><code class="lang-go hljs">// src/net/ipsock.go func ResolveTCPAddr(network, address string) (*TCPAddr, error) { // 检查 `network` 的值 switch network { case "tcp", "tcp4", "tcp6": case "": // a hint wildcard for Go 1.0 undocumented behavior network = "tcp" default: return nil, UnknownNetworkError(network) } // 使用默认解析器对 `address` 进行解析 addrs, err := DefaultResolver.internetAddrList(context.Background(), network, address) if err != nil { return nil, err } // 根据 `network` 和 `address` 返回一个地址 return addrs.forResolve(network, address).(*TCPAddr), nil } </code></code></pre>

从源码中可以看出,参数 <code>network</code> 只能是如下四个值,否则会得到一个错误。

<blockquote>

默认解析器解析地址后返回一个地址列表 <code>addrs</code>,该地址列表既包含了 IPv4 地址,也包含了 IPv6 地址。

</blockquote> <ol><li>"": 将 <code>network</code> 置为 "tcp",这是因为在使用默认解析器对 <code>address</code> 进行解析时根据 <code>network</code> 返回 TCP 地址 <code>*TCPAddr</code>。</li> <li>"tcp": 若 <code>address</code> 是 IPv6 地址,则该函数返回 <code>addrs</code> 中的第一个 <code>IP</code> 是 IPv6 的地址,否则返回 <code>addrs</code> 中的第一个 <code>IP</code> 是 IPv4 的地址。</li> <li>"tcp4": 该函数返回 <code>addrs</code> 中的第一个 <code>IP</code> 是 IPv4 的地址。</li> <li>"tcp6": 该函数返回 <code>addrs</code> 中的第一个 <code>IP</code> 是 IPv6 的地址。</li> </ol><blockquote>

<code>addrs.forResolve</code> 相关源码如下:

</blockquote> <pre><code class="lang-go hljs">// src/net/ipsock.go // An addrList represents a list of network endpoint addresses. type addrList []Addr // isIPv4 reports whether addr contains an IPv4 address. func isIPv4(addr Addr) bool { switch addr := addr.(type) { case *TCPAddr: return addr.IP.To4() != nil ... } return false } // isNotIPv4 reports whether addr does not contain an IPv4 address. func isNotIPv4(addr Addr) bool { return !isIPv4(addr) } // forResolve returns the most appropriate address in address for // a call to ResolveTCPAddr, ResolveUDPAddr, or ResolveIPAddr. // IPv4 is preferred, unless addr contains an IPv6 literal. func (addrs addrList) forResolve(network, addr string) Addr { var want6 bool switch network { ... case "tcp", "udp": // IPv6 literal. (addr contains a port, so look for '[') want6 = count(addr, '[') > 0 } if want6 { return addrs.first(isNotIPv4) } return addrs.first(isIPv4) } // first returns the first address which satisfies strategy, or if // none do, then the first address of any kind. func (addrs addrList) first(strategy func(Addr) bool) Addr { for _, addr := range addrs { if strategy(addr) { return addr } } return addrs[0] } </code></code></pre> <h2>ResolveUDPAddr</h2>

解析过程跟 ResolveTCPAddr 的一样,不过得到的是 <code>*UDPAddr</code>。
<code>UDPAddr</code> 包含的信息如下:

<pre><code class="lang-go hljs">// src/net/udpsock.go type UDPAddr struct { IP IP Port int Zone string // IPv6 scoped addressing zone } </code></code></pre> <h3>源码分析</h3> <pre><code class="lang-go hljs">// src/net/udpsock.go func ResolveUDPAddr(network, address string) (*UDPAddr, error) { // 检查 `network` 的值 switch network { case "udp", "udp4", "udp6": case "": // a hint wildcard for Go 1.0 undocumented behavior network = "udp" default: return nil, UnknownNetworkError(network) } // 使用默认解析器对 `address` 进行解析 addrs, err := DefaultResolver.internetAddrList(context.Background(), network, address) if err != nil { return nil, err } // 根据 `network` 和 `address` 返回一个地址 return addrs.forResolve(network, address).(*UDPAddr), nil } </code></code></pre> <h2>Reference</h2> <ul><li>https://en.wikipedia.org/wiki/IPv6_address</li> <li>https://golang.google.cn/pkg/net/</li> </ul>

到此这篇关于“Golang 网络编程丝绸之路 - TCP/UDP 地址解析”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
Golang 网络编程丝绸之路 - TCP/UDP 地址解析
linux tcp文件分包_教你如何实现《UDP/TCP》可靠网络传输
socket套接字详解(TCP与UDP)
UDP是什么,UDP协议及优缺点
Java数据报编程之广播
电脑不能打开网页,但是QQ可以登陆
什么是MAC地址-基础知识
Golang基础第五篇——golang的gRPC
GoLang之网络
Go 语言的网络编程简介

[关闭]
~ ~