golang TCP/UDP简单入门

net 包里的一些方法

  • ParseIP(string) // 验证IP地址字符串 返回 IP 对象

  • type IPMask []byte // 子网掩码类型

       func IPv4Mask(a, b, c, d byte) IPMask // 用一个四字节的IPv4地址来创建一个掩码
       func (ip IP) DefaultMask() IPMask     // 这是一个IP方法,返回默认的掩码
       func (ip IP) Mask(mask IPMask) IP     // 一个掩码可以使用一个IP地址的方法,找到该IP地址的网络
    
  • 在 net 包的许多函数和方法会返回一个指向IPAddr 的指针,这不过只是一个包含IP类型的结构体, 这种类型的主要
    用途是通过 IP 主机名执行 DNS 查找

       type IPAddr struct {
    	    IP IP
            Zone string // IPv6 scoped addressing zone
       }
       func ResolveIPAddr(net, addr string) (*IPAddr, error)  // 通过域名 返回主机IP
       func LookupHost(host string) (addrs []string, err error) // 一个域名可能有多个地址
    
  • 服务运行在主机上,一个主机可以运行多个服务 (TCP, UDP, SCTP …) 使用端口来加以区分(1 ~ 65535)

    • unix 系统中, /etc/service 文件列出了常用的端口, go 有一个函数可以获取该文件 func LookupPort(network, service string) (port int, err error)
  • TCPAddr 类型包含一个IP 和 一个 port 的结构 :

    type TCPAddr struct {
       IP      IP
       Port    int
    }
    func ResolveTCPAddr(net, addr string) (*TCPAddr, error) // 创建一个 TCPAddr  addr-www.baidu.com:80
    
  • TCP Sockets

   func (c *TCPConn) Write(b []byte) (n int, err error)
   func (c *TCPConn) Read(b []byte) (n int, err error)   // 底层实际上还是调用 ReadFile 方法 读取 TCPConn 句柄里的数据到 b 切片里  e := ReadFile(fd, p, &done, nil)  fd - TCPConn 以下 Read 方法跟这个一样
   func DialTCP(net string, laddr, raddr *TCPAddr) // net-(tcp4,tcp6,tcp) laddr-nil 
  • TCP 通信

       func main(){
    	    service := "127.0.0.1:8099"
            tcpAddr, err := net.ResolceTCPAddr("ip4", service) // 传入域名:端口 / IP:端口 返回一个TCP类型
            listener, err := net.ListenTCP("tcp", tcpAddr) // 监听端口 也可以直接用 net.Listen("tcp", "127.0.0.1:8099") 来监听端口
            for {//不间断的接受客户端请求
         	    conn, err := listener.Accept() // 这步会阻塞到这 直到有客户端请求
      	        if err != nil {
            	    continue
                }
      	        go handleClient(conn) // 多线程处理客户端请求
           }
       }
       
       func handleClient(conn net.Conn) {
    	    defer conn.Close()
            var buf [512]byte
            for {
       	        n, err := conn.Read(buf[0:])
    	        _, err = conn.Write(buf[0:n])
           }
        
       }
    
    • 超时

      • 服务端会断开那些超时的客户端,如果他们响应的不够快,比如没有及时的往服务端写一个请求。
        func (c *TCPConn) SetTimeout(nsec int64) error // 用在套接字读写前(Accept)
    • 存活状态

      • 即使没有任何通信 一个客户端可能希望保持连接到服务器的状态
        func (c *TCPConn) SetKeepAlive(keepalive bool) error
  • UDP 通信

    • 主要方法
      func ResolveUDPAddr(net, addr string) (*UDPAddr, error) // 解析地址 生成 UDPAddr 类型
      func DialUDP(net string, laddr, raddr *UDPAddr) // 连接 UDP服务器
      func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) // UDP协议监听端口
      func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) // 处理客户端传过来的数据
      func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) // 发送数据给客户端
      func (c *conn) Write(b []byte) (int, error) // 发送数据给服务端
      func (c *conn) Read(b []byte) (int, error) // 读取服务端发送过来的数据
      
TCP 简单实现
  • 服务端 这个跟上面的一样
func main(){
   	    service := "127.0.0.1:8099"
	        tcpAddr, err := net.ResolceTCPAddr("ip4", service) // 传入域名:端口 / IP:端口 返回一个TCP类型
           listener, err := net.ListenTCP("tcp", tcpAddr) // 监听端口 也可以直接用 net.Listen("tcp", "127.0.0.1:8099") 来监听端口
           for {//不间断的接受客户端请求
        	    conn, err := listener.Accept() // 这步会阻塞到这 直到有客户端请求
     	        if err != nil {
  	        	    continue
  	            }
     	        go handleClient(conn) // 多线程处理客户端请求
          }
      }
      
      func handleClient(conn net.Conn) {
   	    defer conn.Close()
	        var buf [512]byte
	        for {
      	        n, err := conn.Read(buf[0:])
   	        _, err = conn.Write(buf[0:n])
          }
	    
      }
  • 客户端简单实现 ~ 简化版
fmt.Println("please input host:port -")
	var host string
	fmt.Scanf("%s\n", &host)
	tcpAddr,err := net.ResolveTCPAddr("tcp4", host)
	conn, err := net.DialTCP("tcp", nil, tcpAddr)
	bt, err := ioutil.ReadAll(conn)
	if err != nil {
		fmt.Println("one : ", err)
	}
	fmt.Println(string(bt))
	result, err := ioutil.ReadAll(conn)

	fmt.Println("获取到的数据是 : \n", string(result))
UDP 简单实现
  • 服务端
addr := "127.0.0.1:8097"
	udpAddr, err := net.ResolveUDPAddr("udp4", addr) // 生成 UDPAddr 类型
	if err != nil {
		fmt.Println("udp addr resolve err : ", err)
	}
	conn, err := net.ListenUDP("udp4", udpAddr) // 开启 UDP服务 监听端口
	if err != nil {
		fmt.Println("udp listen failed : ", err)
	}
	var buf [512]byte
	for {
		n, clientAddr, err := conn.ReadFromUDP(buf[0:]) // 读取客户端发送过来的数据 clientAddr-客户端地址 UDP相比TCP不需要三次握手 是迅速、无状态的,每次请求都会带上自己的IP等标识信息
		if err != nil {
			fmt.Println("udp read failed : ", err)
		}
		fmt.Println("get client data : ", string(buf[0:n]))
		_, err = conn.WriteToUDP([]byte(time.Now().String()), clientAddr) // 发送数据给客户端
		if err != nil {
			fmt.Println("write udp failed : ", err)
		}
	}
  • 客户端
addrPort := "127.0.0.1:8097"
	udpAddr,err := net.ResolveUDPAddr("udp4", addrPort) // 把域名:端口 / IP:端口 解析成 UDPAddr 类型
	if err != nil {
		fmt.Println("UDPAddr trans failed", err)
	}
	conn, err := net.DialUDP("udp4", nil, udpAddr) // 连接服务器
	if err != nil {
		fmt.Println("udp 连接错误", err)
	}
	var buf [512]byte
	for{
		_, err = conn.Write([]byte("hello zzh")) // 发送数据给UDP服务器
		if err != nil {
			fmt.Println("udp 发送数据失败", err)
		}
		n, err := conn.Read(buf[0:]) // 读取服务器发送的数据
		if err != nil {
			fmt.Println("read udp failed : ", err)
		}
		fmt.Println("client get data : ", string(buf[0:n]))
		time.Sleep(2e9)

关联文章 - OSI七层模型的理解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值