知识点 Tcp与Udp (一)

余生颓废 提交于 2019-11-27 15:29:22

一、TCP/UDP协议
TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)协议属于传输层协议。其中TCP提供IP环境下的数据可靠传输,
它提供的服务包括数据流传送、可靠性、有效流控、全双工操作和多路复用。通过面向连接、端到端和可靠的数据包发送。通俗说,
它是事先为所发送的数据开辟出连接好的通道,然后再进行数据发送;而UDP则不为IP提供可靠性、 流控或差错恢复功能。一般来说,
TCP对应的是可靠性要求高的应用,而UDP对应的则是可靠性要求低、传输流量大,传输速度快的应用

TCP支持的应用协议主要 有:Telnet、FTP、SMTP等;UDP支持的应用层协议主要有:NFS(网络文件系统)、SNMP(简单网络管理协议)、
DNS(主域名称系 统)、TFTP(通用文件传输协议)等。

TCP/IP协议与低层的数据链路层和物理层无关,这也是TCP/IP的重要特点。

二、TCP 和 UDP 区别
面向连接vs无连接
TCP 有三次握手的连接过程,UDP 适合消息的多播发布,从单个点向多个点传输消息。
可靠性
TCP 利用握手, 确认(ACK) 和重传的机制,提供了可靠性保证,而 UDP 可能丢失,不知道到底有没有接收。
有序性
TCP 利用序列号保证了消息包的的顺序交付,到达可能无序,但 TCP 会排序。
速度
TCP 速度比较慢,因为要创建连接,保证消息的可靠性和有序性等,需要做额外的很多事情,UDP 更适合对速度比较敏感的应用,
比如在线视频媒体,电视广播,多人在线游戏等。
头字节大小
三、 Go语言TCP客户端与服务端实现
Go语言实现的tcp服务端通信模型
TCPServer
package main

import (
  "fmt"
  "io"
  "net"
  "os"
)

func main(){
  //服务器端一般不定位具体的客户端套接字
  tcpaddr, err := net.ResolveTCPAddr("tcp",":8848")
  if err != nil {
    fmt.Fprintf(os.Stderr,"Server ResolveTCPAddr fail,err :%v", err)
    return
  }

  serverfd, err := net.ListenTCP("tcp",tcpaddr)
  if err != nil {
    fmt.Fprintf(os.Stderr,"Server ListenTCP fail,err :%v", err)
    return
  }

  defer serverfd.Close()

  for{
    conn, err := serverfd.AcceptTCP()
    if err != nil {
      fmt.Fprintf(os.Stderr,"Server Accept fail,err :%v",err)
      return
    }

    go handleClient(conn)
  }
}

func handleClient(conn net.Conn){
  defer conn.Close()

  fmt.Printf("Welcome %v connect",conn.RemoteAddr().String())

  for{
    buf := make([]byte,1024)
    _, err := conn.Read(buf)
    if err != nil{
      fmt.Fprintf(os.Stderr,"Server read fail,err: %v",err)
      break
    }

    fmt.Printf("Read Buf:%s",string(buf))

    _, err = conn.Write(buf)
    if err != nil {
      fmt.Fprintf(os.Stderr,"Server write fail")
      break
    }
  }
}
Go server端程序模型为
//go-tcpsock/server.go
func HandleConn(conn net.Conn) {
  defer conn.Close()

  for {
    // read from the connection
    // ... ...
    // write to the connection
    //... ...
  }
}

func main() {
  listen, err := net.Listen("tcp", ":8888")
  if err != nil {
    fmt.Println("listen error: ", err)
    return
  }

  for {
    conn, err := listen.Accept()
    if err != nil {
      fmt.Println("accept error: ", err)
      break
    }

    // start a new goroutine to handle the new connection
    go HandleConn(conn)
  }
}
Go语言实现的TCP客户端通信模型
TCPClient
package main

import (
  "bufio"
  "fmt"
  "net"
  "os"
)

func main(){
  tcpaddr, err := net.ResolveTCPAddr("tcp","127.0.0.1:8848")
  if err != nil {
    fmt.Fprintf(os.Stderr,"Client ResolveTCPAddr fail, err: %v",err)
    return
  }

  conn, err := net.DialTCP("tcp",nil,tcpaddr)
  if err != nil {
    fmt.Fprintf(os.Stderr,"Client DialTCP fail, err: %v",err)
    return
  }

  defer conn.Close()

  reader := bufio.NewReader(os.Stdin)
  for{
    buf, err := reader.ReadString('\n')
    if err != nil{
      fmt.Fprintf(os.Stderr,"ReadString fail,err :%v",err)
      return
    }

    _, err = conn.Write([]byte(buf))
    if err != nil {
      fmt.Fprintf(os.Stderr,"Write fail,err: %v",err)
      return
    }

    //readBuf 记住需要分配内存
    readBuf := make([]byte,1024)
    _, err = conn.Read(readBuf)
    if err != nil {
      fmt.Fprintf(os.Stderr,"Read fail,err :%v",err)
      return
    }

    fmt.Printf("read buf:%s\n",string(readBuf))

  }
}
四、Go语言UDP服务端与客户端实现
Go语言udp服务端实现
package main

import (
  "fmt"
  "net"
  "os"
)

func main() {
  addr, err := net.ResolveUDPAddr("udp", ":8848")
  if err != nil {
    fmt.Fprintf(os.Stderr, "udp server ResolveUDPAddr fail,err :%v", err)
    return
  }

  conn, err := net.ListenUDP("udp", addr)
  if err != nil {
    fmt.Fprintf(os.Stderr, "udp server ListenUDP fail,err :%v", err)
    return
  }
  defer conn.Close()

  for {
    buf := make([]byte, 1024)
    _, clientAddr, err := conn.ReadFromUDP(buf)
    if err != nil {
      fmt.Fprintf(os.Stderr, "udp server ReadFromUDP fail,err: %v", err)
      continue
    }

    fmt.Printf("Recv Msg:%s\n", string(buf))

    go func() {
      _, err = conn.WriteToUDP(buf, clientAddr)

      if err != nil {
        fmt.Printf("udp server WriteToUDP fail,err: %v\n", err)
        return
      }
    }()
  }
}

Go语言udp客户端实现
package main

import (
  "bufio"
  "fmt"
  "net"
  "os"
)

func main(){
  if len(os.Args) != 2 {
    fmt.Fprintf(os.Stderr,"Usage:%v host:port",os.Args[0])
    return
  }

  addr, err := net.ResolveUDPAddr("udp",os.Args[1])
  if err != nil {
    fmt.Fprintf(os.Stderr,"udp client ResolveUDPAddr fail,err :%v",err)
    return
  }

  conn, err := net.DialUDP("udp",nil,addr)
  if err != nil {
    fmt.Fprintf(os.Stderr,"udp client DialUDP fail,err :%v",err)
    return
  }

  scanner := bufio.NewScanner(os.Stdin)
  for scanner.Scan() {
    buf := scanner.Text()

    fmt.Printf("input buf:%s\n",buf)

    _, err := conn.Write([]byte(buf))
    if err != nil {
      fmt.Fprintf(os.Stderr,"udp client Write fail,err :%v",err)
      return
    }

    readBuf := make([]byte,1024)
    _, err = conn.Read(readBuf)
    if err != nil{
      fmt.Fprintf(os.Stderr,"udp client read fail,err :%v",err)
      return
    }

    fmt.Printf("Read buf:%s\n",readBuf)
  }
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!