博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
go tcp 与 udp
阅读量:6517 次
发布时间:2019-06-24

本文共 4372 字,大约阅读时间需要 14 分钟。

  hot3.png

TCP 与 UDP

TCP

TCP 即传输控制协议/网间协议,是一种面向连接(连接导向)的、可靠的、基于字 节流的一个端到端(Peer-to-Peer)的传输层协议.

如文件传送协议 FTP、网络终端协议 TELNET、SMTP、POP3、HTTP 协义等

获取本地的网络地址列表

这个获取的是本地如利用命令 ifconfig 看到的ip地址

可以去go获取本地ip地址这个博客看直接使用代码

func InterfaceAddrs() ([]Addr, error)

package mainimport (	"fmt"	"net")func main() {	addr, err := net.InterfaceAddrs()	if err != nil {		fmt.Println(err)	}	fmt.Println(addr)}

获取主机所对应的IP

也就是获取远程url 对应主机对应在互联网中的ip地址

func LookupIP(host string) (addrs []IP, err error)

用来获取主机所对应的 IP 地址。IP 是一个[]byte 类型,用来表示一个 IP 地址,定义如

package mainimport (	"fmt"	"net")func main() {	ips, err := net.LookupIP("www.baidu.com")	if err != nil {		fmt.Println(err)	}	fmt.Println(ips)}

建立TCPAddr

func ResolveTCPAddr(net, addr string) (*TCPAddr, os.Error)

该函数用来创建一个 TCPAddr,第一个参数为,tcp,tcp4 或者 tcp6,addr 是一个字符串,由 主机名或 IP 地址,以及":"后跟随着端口号组成.

例如: "127.0.0.1:8080",如果地址是一个 IPv6 地址,由于已经有冒号,主机部分,必须放在方括号 内, 例如:"[::1]:8080"。

package mainimport (	"fmt"	"net")func main() {	ip, err := net.ResolveTCPAddr("tcp", "127.0.0.1:80")	if err != nil {		fmt.Println(err)	}	fmt.Println(ip, ip.IP, ip.Port, ip.Network()) //127.0.0.1:80 127.0.0.1 80 tcp}

服务端监听TCP连接

func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error)在指定的端口监听,等待客户端的链接

func (l *TCPListener) AcceptTCP() (*TCPConn, error) 用来接受客户端的请求,返回一个 Conn 链接,通过这个 Conn 来与客户端的进行通信。

func (l *TCPListener) Accept() (Conn, error) 底层实现是一样的

func (c *TCPConn) Write(b []byte) (int, error) 向 TCPConn 网络链接发送数据,b 是要发送的内容,返回值 int 为实际发送的字节数。

func (c *TCPConn) Read(b []byte) (int, error) 从 TCPConn 网络链接接收数据。返回值 Int 是实际接收的字节数。b 是接收的数据。

func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) 用来链接远程服务器。net 可以是 tcp、tcp4、tcp6 中的一个。Laddr 为本地地址,通常 传 null,raddr 是要链接的远端服务器的地址。成功返回 TCPConn,用返回的 TCPConn 可以 向服务器发送消息,读取服务器的响应信息。

//作为一个TCP的客户端,基本的操作流程如下:service="www.google.com:80"tcpAddr, err := net.ResolveTCPAddr("tcp4", service) //建立TCPAddrconn, err := net.DialTCP("tcp", nil, tcpAddr) // 连接服务器_, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))  // 写信息_, err = conn.Read(b) / result, err := ioutil.ReadAll(conn) //读取返回值//服务器的基本操作流程为:service:=":9090"tcpAddr, err := net.ResolveTCPAddr("tcp4", service) //建立TCPAddrl,err := net.ListenTCP("tcp",tcpAddr) //监听地址conn,err := l.Accept() //接收消息go Handler(conn) //此处使用go关键字新建线程处理连接,实现并发

注意:TCP 协议需要通信双方约定数据的传输格式,否则接收方无法判断数据是否 接收完成。

所以一般会自己去定义一个协议,比如定义[8]byte协议头,前4个byte放长度,后4个放状态。

如果发送端,发送数据后,调用 Close 关闭连接,不等待服务端的返回数据,服务端可 以用 ioutil.ReadAll 来读取数据,这时可以判断出 EOF,读取结束。 但如果客户端发送数据 后,没有关闭,而是等待服务端的数据返回,用 ReadAll 是不行的。 这里可以设置接收客户端超时,如果接收的消息超时需要有所处理

示例
//服务端

TCP 协议需要通信双方约定数据的传输格式,否则接收方无法判断数据是否 接收完成。在上面的例子中,SendData 用来发送数据,在数据发送前,添加结束标记, buf = append(buf, 0),用来表示数据发送结束。接收方收到 0 说明数据接收完成。 要么接收无法判断数据是否接收完。 如果发送端,发送数据后,调用 Close 关闭连接,不等待服务端的返回数据,服务端可 以用 ioutil.ReadAll 来读取数据,这时可以判断出 EOF,读取结束。但如果客户端发送数据 后,没有关闭,而是等待服务端的数据返回,用 ReadAll 是不行的。所以在上面的例子中, 用 0 来示数据的发送完成。

UDP

UDP 是用户数据报协议(User Datagram Protocol,UDP)的简称,UDP 协议提供的是 面向无连接的、不可靠的数据报投递服务。当使用 UDP 协议传输信息流时,用户应用程序 必须负责解决数据报丢失、重复、排序,差错确认等问题。 因为 UDP 不是面向链接的,所 以资源消耗小,处理速度快,通常音频、视频和普通数据在传送时使 UDP 较多。如 QQ 使 用的就是 UDP 协议。UDP 适用于一次只传少量数据的环境,数据报的最大长度根据操作环境的不同而各异。

从理论上说,包含报头在内的数据报的最大长度为 65535 字节。不过,一 些实际应用往往会限制数据报的大小,有时会降低到 8192 字节。

建立UDPAddr

func ResolveUDPAddr(net, addr string) (*UDPAddr, error) 把 addr 地址字符串,解析成 UDPAddr 地址。net 可以是”udp”,”udp4”,”udp6”,addr 是一 个地址字符串,由主机名或 IP 地址,以及“:”后面跟着的端口号组成。如果是 IPv6,主机 部分必须在方括内,如[::1]8080

服务端监听UDP连接

func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) 在指定的地址(laddr)监听,等待 UDP 数据包的到达。返回*UDPConn,可以使用连接的 ReadFrom 函数来读取 UDP 数据,用 WriteTo 来向客户端发送数据。

func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) 服务端用来读取 UDP 数据。Addr 是发送方的地址。

func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) 向 addr 发数据时用。b 是要发送的数据,addr 是接收方的地址。

func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) 连接到远端服务器 raddr,net 参数必须是”udp”,”udp4”,”udp6”中的一个。Laddr 通常为 nil,如果不是 nil 将使用 laddr 来连接到服务端。

func (c *UDPConn) Write(b []byte) (int, error) 用来向服务端发送数据。

func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) 与 ReadFrom 相同,用来读取发来 UDP 数据。

示例
 

在前面 TCP 的示例里,我们有约定,一条消息的结束标记。在 UDP 里,不需要有约定 结束标记,但需要约定,UDP 报文的最大长度。UDP 的数据,必须一次接收完成。比如上 面的例子中,我们用,var buf [1024]byte,定义了 1KB 的缓冲区来接收数据。因为我们发送 的数据量不大,所以可以一次读取。如果我们把上面的缓冲区改两个字节 var buf [2]byte 会 怎么样?大家可以自己试一下,会报一个错误: WSARecvFrom udp 0.0.0.0:7070: More data is available. 所以,UDP 通信的双方需要约定报文的最大长度。

示例等下补充。。。。。。。。

参考

一起学go.pdf

PS: 觉得不错的请点个赞吧!! (ง •̀_•́)ง

转载于:https://my.oschina.net/solate/blog/794439

你可能感兴趣的文章
Stack Overflow上最热门问题是什么?
查看>>
微软Build 2017第二天:跨平台跨硬件开发体验
查看>>
Java EE跟JCP说再见
查看>>
分布式团队面临的五大问题及解决办法
查看>>
GitLab 8.7发布
查看>>
【互联网专场】以云为桥,腾讯云助互联网行业加速连接人工智能
查看>>
如何将C# 7类库升级到C# 8?使用可空引用类型
查看>>
有货移动Web端性能优化探索实践
查看>>
“软”苹果水逆的一周:杂志服务崩溃,新机型遭泄露,芯片首架离职
查看>>
Gerrit代码Review入门实战
查看>>
Facebook 推出 React Native - iOS 移动开发周报
查看>>
微软整合Azure Application Services,以App Service针对多类应用提供一站式服务
查看>>
Racket 6.11提供了稳定的细化类型和依赖函数特性
查看>>
bootstrap学习
查看>>
干货:小程序开发文档和设计指南要点详解
查看>>
自做Windows上界面美观的PHP集成环境软件
查看>>
[deviceone开发]-纳豆项目源码开源
查看>>
Javascript加载执行方法总结
查看>>
温故知新之JS基础
查看>>
关于js高级程序设计第三版中关于arguments论述的一个错误
查看>>