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