前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go tcp 与 udp

go tcp 与 udp

作者头像
solate
发布2019-07-22 16:16:40
1.1K0
发布2019-07-22 16:16:40
举报
文章被收录于专栏:solate 杂货铺

TCP 与 UDP

TCP

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

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

获取本地的网络地址列表

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

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

func InterfaceAddrs() ([]Addr, error)

代码语言:javascript
复制
package main

import (
	"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 地址,定义如

代码语言:javascript
复制
package main

import (
	"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"。

代码语言:javascript
复制
package main

import (
	"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 可以 向服务器发送消息,读取服务器的响应信息。

代码语言:javascript
复制
//作为一个TCP的客户端,基本的操作流程如下:
service="www.google.com:80"
tcpAddr, err := net.ResolveTCPAddr("tcp4", service) //建立TCPAddr
conn, 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) //建立TCPAddr
l,err := net.ListenTCP("tcp",tcpAddr) //监听地址
conn,err := l.Accept() //接收消息
go Handler(conn) //此处使用go关键字新建线程处理连接,实现并发

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

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

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

示例
代码语言:javascript
复制
//服务端

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 数据。

示例
代码语言:javascript
复制

在前面 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: 觉得不错的请点个赞吧!! (ง •̀_•́)ง

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • TCP
    • 获取本地的网络地址列表
      • 获取主机所对应的IP
        • 建立TCPAddr
          • 服务端监听TCP连接
            • 示例
        • UDP
          • 建立UDPAddr
            • 示例
        • 服务端监听UDP连接
        • 参考
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档