干货满满: 网络协议科普-go语言版本

2,161 阅读4分钟

本文正在参与 “网络协议必知必会”征文活动

🌑 o介绍下OSI七层模型

OIP-C.jpg

🕛 o.1物理层Physical

物理层Physical Layer 在局域网上发送数据帧 Data Frame,它负责管理电脑通信设备和网络媒体之间的互通。包括了针脚、电压、线缆规范、集线器、中继器、网卡、主机接口卡等。

图片一

图片一:两台计算机通过单个交换机通讯

图片一网口 网线光纤 交换机都属于物理层

🕧 o.2数据链路层Data Link layer

数据链路层Data Link Layer 负责网络寻址、错误侦测和改错。当表头和表尾被加至数据包时,会形成信息框Data Frame。数据链表头DLH是包含了物理地址和错误侦测及改错的方法。数据链表尾(DLT)是一串指示数据包末端的字符串。例如以太网、无线局域网Wi-Fi和通用分组无线服务GPRS等。

分为两个子层:逻辑链路控制logical link control,LLC子层和介质访问控制Media access control,MAC子层。

🕐 o.3网络层Network layer

网络层Network Layer决定数据的路径选择和转寄,将网络表头NH加至数据包,以形成分组。网络表头包含了网络资料。例如:互联网协议IP等。

🕜 o.4传输层Transport layer

传输层Transport Layer 把传输表头TH加至资料以形成分组。传输表头包含了所使用的协议等发送信息。例如:传输控制协议TCP等。

🕑 o.5会话层Session layer

会话层Session Layer负责在数据传输中设置和维护计算机网络中两台计算机之间的通信连接。

🕝 o.6表示层Presentation layer

表示层Presentation Layer把数据转换为能与接收者的系统格式兼容并适合传输的格式。

🕒 o.7应用层Application layer

应用层Application Layer提供为应用软件而设计的接口,以设置与另一应用软件之间的通信。例如:HTTP HTTPS FTP Telnet SSH SMTP POP3等。

🌒 1 什么是socket

src=http___img.blog.csdn.net_20160911152508055&refer=http___img.blog.csdn.jpg socket是一种操作系统提供的进程间通信机制.

操作系统中,通常会为应用程序提供一组应用程序接口 API,称为套接字接口(英语:socket API)。应用程序可以通过套接字接口,来使用网络套接字,以进行资料交换。最早的套接字接口来自于4.2 BSD,因此现代常见的套接字接口大多源自Berkeley套接字标准。在套接字接口中,以IP地址端口组成套接字地址socket address。远程的套接字地址,以及本地的套接字地址完成连线后,再加上使用的协议protocol,这个五元组five-element tuple,作为套接字对socket pairs,之后就可以彼此交换资料。例如,在同一台计算机上,TCP协议与UDP协议可以同时使用相同的port而互不干扰。 操作系统根据套接字地址,可以决定应该将资料送达特定的行程线程

🌓 2 TCP

  • 协议介绍

TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流传输层信协议。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能。 UDP是同一层内另一个重要的传输协议。

  • tcp服务端 服务器功能
1 监听端口
2 接受客户端连接请求
3 处理消息

server.go

package server

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

func process(conn net.Conn) {
   defer conn.Close() // 关闭连接
   for {
      reader := bufio.NewReader(conn)
      var buf [128]byte
      n, err := reader.Read(buf[:]) // 读取数据
      if err != nil {
         fmt.Println("read from client failed, err:", err)
         break
      }
      recvStr := string(buf[:n])
      fmt.Println("收到client端发来的数据:", recvStr)
      conn.Write([]byte(recvStr)) // 发送数据
   }
}

func main() {
   listen, err := net.Listen("tcp", "127.0.0.1:8080")
   if err != nil {
      fmt.Println("listen failed, err:", err)
      return
   }
   for {
      conn, err := listen.Accept() // 建立连接
      if err != nil {
         fmt.Println("accept failed, err:", err)
         continue
      }
      go process(conn) // 启动一个goroutine处理连接
   }
}
  • tcp客户端 客户端功能
1 与服务器建立连接
2 收发数据
3 关闭连接

client.go

package server

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

// tcp/client/main.go

// 客户端
func main() {
   conn, err := net.Dial("tcp", "127.0.0.1:8080")
   if err != nil {
      fmt.Println("err :", err)
      return
   }
   defer conn.Close() // 关闭连接
   inputReader := bufio.NewReader(os.Stdin)
   for {
      input, _ := inputReader.ReadString('\n') // 读取用户输入
      inputInfo := strings.Trim(input, "\r\n")
      if strings.ToUpper(inputInfo) == "Q" { // 如果输入q就退出
         return
      }
      _, err = conn.Write([]byte(inputInfo)) // 发送数据
      if err != nil {
         return
      }
      buf := [512]byte{}
      n, err := conn.Read(buf[:])
      if err != nil {
         fmt.Println("recv failed, err:", err)
         return
      }
      fmt.Println(string(buf[:n]))
   }
}
  • 消息收发

server.png

client.png

🌕 3 UDP

  • 协议介绍 UDP(User Datagram Protocol)是一个简单的面向资料包通信协议,位于OSI模型传输层

  • udp服务器 server.go

package main

import (
   "fmt"
   "net"
)

// UDP/server/main.go

// UDP server端
func main() {
   listen, err := net.ListenUDP("udp", &net.UDPAddr{
      IP:   net.IPv4(0, 0, 0, 0),
      Port: 30000,
   })
   if err != nil {
      fmt.Println("listen failed, err:", err)
      return
   }
   defer listen.Close()
   for {
      var data [1024]byte
      n, addr, err := listen.ReadFromUDP(data[:]) // 接收数据
      if err != nil {
         fmt.Println("read udp failed, err:", err)
         continue
      }
      fmt.Printf("data:%v addr:%v count:%v\n", string(data[:n]), addr, n)
      _, err = listen.WriteToUDP(data[:n], addr) // 发送数据
      if err != nil {
         fmt.Println("write to udp failed, err:", err)
         continue
      }
   }
}
  • udp客户端
package main

import (
   "fmt"
   "net"
)

// UDP 客户端
func main() {
   socket, err := net.DialUDP("udp", nil, &net.UDPAddr{
      IP:   net.IPv4(0, 0, 0, 0),
      Port: 30000,
   })
   if err != nil {
      fmt.Println("连接服务端失败,err:", err)
      return
   }
   defer socket.Close()
   sendData := []byte("Hello server")
   _, err = socket.Write(sendData) // 发送数据
   if err != nil {
      fmt.Println("发送数据失败,err:", err)
      return
   }
   data := make([]byte, 4096)
   n, remoteAddr, err := socket.ReadFromUDP(data) // 接收数据
   if err != nil {
      fmt.Println("接收数据失败,err:", err)
      return
   }
   fmt.Printf("recv:%v addr:%v count:%v\n", string(data[:n]), remoteAddr, n)
}
  • 消息收发

udp_server.png

udp_client.png