互联网协议介绍引入
1. 物理层(Physical Layer):
- 功能:物理层负责定义物理介质传输数据的方式和规范,它传输的是原始数据比特流。
- 协议:Ethernet、Wi-Fi、USB、光纤等。
- 例子:将数据通过网线传输的过程类似于我们通过电话线进行声音通信。
2. 数据链路层(Data Link Layer):
- 功能:数据链路层负责将数据分成帧,并进行传输错误的检测和纠正。
- 协议:Ethernet(MAC地址)、PPP(点对点协议)等。
- 例子:当我们接收到一封电子邮件时,电子邮件被分成小块,每个块都有一个标识符,以确保它们的正确接收。
3. 网络层(Network Layer):
- 功能:网络层负责在网络中选择最佳的路径进行数据传输和路由。
- 协议:IP(Internet协议)、ICMP(Internet控制消息协议)等。
- 例子:当我们使用导航应用程序时,它会根据我们的位置、交通情况和其他因素决定最佳路线。
4. 传输层(Transport Layer):
- 功能:传输层负责提供可靠的端到端数据传输和错误恢复。
- 协议:TCP(传输控制协议)、UDP(用户数据报协议)等。
- 例子:当我们下载文件时,传输层确保文件被正确地分割成数据包,并且在接收端按正确顺序重新组装。
5. 会话层(Session Layer):
- 功能:会话层负责建立、管理和终止网络中的会话。
- 协议:TLS(安全传输层协议)、SSH(安全外壳协议)等。
- 例子:当我们在网上购物时,会话层确保我们与商家之间的通信是加密和安全的。
6. 表示层(Presentation Layer):
- 功能:表示层负责数据的格式化、加密和压缩,确保不同系统间的数据能正确解释和理解。
- 协议:JPEG(图像压缩标准)、MPEG(音视频压缩标准)等。
- 例子:当我们分享相片时,表示层负责将图像转换成适合传输和显示的格式。
7. 应用层(Application Layer):
- 功能:应用层负责发送和接收应用程序之间的数据,并提供应用程序所需的服务。
- 协议:HTTP(超文本传输协议)、FTP(文件传输协议)、SMTP(简单邮件传输协议)等。
- 例子:当我们使用浏览器访问网页时,应用层使用HTTP协议来请求和接收网页内容。
如下图所示,发送方的HTTP数据经过互联网的传输过程中会依次添加各层协议的标头信息,接收方收到数据包之后再依次根据协议解包得到数据。
socket图解
什么是套接字
Socket(套接字)是一种用于实现网络通信的编程接口;
它允许不同的计算机通过网络互相传递数据;
Socket提供了一种标准的编程接口,使得开发者可以使用通用的网络协议(如TCP/IP)进行网络通信。
下面举生活中的例子:
Socket是应用层与传输层之间的接口,它基于计算机网络原理,将网络传输分为两个角色:服务器(Server)和客户端(Client)
CS架构
- 服务器端(Server):服务器端监听特定的网络端口,等待客户端的连接请求。一旦接收到连接请求,服务器端创建一个新的Socket与客户端进行通信。
- 客户端(Client):客户端发起连接请求,并通过Socket与服务器端建立通信。客户端可以发送请求数据到服务器,并接收服务器的响应数据。
Socket操作涉及以下几个主要步骤:
1. 创建Socket:服务器端和客户端都需要创建一个Socket对象,用来进行通信(该对象包含了IP地址和端口号等信息)
2. 绑定Socket:服务器端需要将Socket绑定到一个具体的IP地址和端口号上,以便客户端能够连接。
3. 监听连接:服务器端通过Socket监听特定的端口,等待客户端的连接请求。
4. 接受连接:一旦服务器端接收到连接请求,它会创建一个新的Socket对象与客户端进行通信。
5. 数据传输:通过Socket对象,服务器端和客户端可以相互发送数据。
6. 关闭连接:通信完成后,服务器和客户端都可以关闭Socket连接。
生活中的例子可以是使用手机应用程序与服务器进行通信。举个例子,考虑一个聊天应用程序,其包括一个服务器和多个客户端。服务器负责接收和分发消息,而客户端负责发送和接收用户的消息。
在这个场景中,服务器端的应用程序创建了一个Socket并在指定端口上侦听。多个客户端应用程序也创建了各自的Socket对象,并使用服务器的IP地址和端口号连接到服务器。
一旦连接建立,客户端通过其Socket向服务器发送消息。服务器接收到消息后,可以将其转发给其他客户端。这样,通过Socket的使用,服务器和客户端可以实现实时的聊天功能。
总结来说,Socket是一种网络编程接口,用于在服务器端和客户端之间建立通信。通过Socket,计算机可以通过网络传输数据,实现各种应用程序的网络通信。
常用的Socket类型有两种:流式Socket和数据报式Socket,流式是一种面向连接的Socket,针对于面向连接的TCP服务应用,数据报式Socket是一种无连接的Socket,针对于无连接的UDP服务应用
TCP:比较靠谱,面向连接,比较慢
UDP:不是太靠谱,比较快
前提概念几则
net包
Go语言实现TCP通信
TCP协议
TCP/IP(Transmission Control Protocol/Internet Protocol) 即传输控制协议/网际协议,是一种面向连接(连接导向)的、可靠的、基于字节流的传输层(Transport layer)通信协议,因为是面向连接的协议,数据像水流一样传输,会存在黏包问题。
TCP服务端
一个TCP服务端可以同时连接很多个客户端,例如世界各地的用户使用自己电脑上的浏览器访问淘宝网。因为Go语言中创建多个goroutine实现并发非常方便和高效,所以我们可以每建立一次链接就创建一个goroutine去处理。
TCP服务端程序的处理流程:
1.监听端口
2.接收客户端请求建立链接
3.创建goroutine处理链接。
TCP服务端代码如下:
package main
import (
"bufio"
"fmt"
"net"
)
// 服务端
func process(conn net.Conn) {
defer conn.Close() // 关闭连接
for {
reader := bufio.NewReader(conn)
var huancun [128]byte
n, err := reader.Read(huancun[:]) // 读取数据
if err != nil {
fmt.Println("从客户端读取数据失败,报错为:", err)
break
}
data := string(huancun[:n])
fmt.Println("收到client端发来的数据:", data)
conn.Write([]byte(data)) // 发送数据
}
}
func main() {
listen, err := net.Listen("tcp", "127.0.0.1:30000")
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服务器程序,它监听在本地的30000端口上,并接受客户端的连接。
一旦有连接建立,就会启动一个goroutine来处理连接。
在处理连接的goroutine中,首先创建一个bufio.Reader对象来读取客户端发送的数据。
然后创建一个长度为128的字节数组作为缓冲区,
使用reader.Read()方法从客户端读取数据,并将读取到的数据存储在缓冲区中。
如果读取过程中发生错误,就打印错误信息并退出循环。
否则,将读取到的数据转换为字符串,并打印出来。然后将读取到的数据通过conn.Write()方法发送回客户端。
在main函数中,首先使用net.Listen()方法创建一个监听器,监听在本地的30000端口上。
如果监听失败,就打印错误信息并返回。否则,进入一个无限循环,不断接受客户端的连接。
在每次接受连接时,如果出现错误,则打印错误信息并继续下一次循环。
否则,启动一个goroutine来处理该连接,即调用process()函数。这样可以同时处理多个客户端的连接。
编译为可执行文件
go build -o server.exe
TCP客户端模拟
package main
import (
"bufio"
"fmt"
"net"
"os"
"strings"
)
// 客户端
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:30000")
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]))
}
}
这是一个基于TCP的简单客户端代码。它通过网络连接到指定的地址和端口
并且可以发送用户输入的数据并接收服务器返回的数据。
在主函数中,首先通过`net.Dial()`函数建立与服务器的连接,并检查是否有错误发生。
如果有错误,将打印错误信息并返回。
然后,通过`bufio.NewReader()`创建一个读取用户输入的读取器。
然后使用一个无限循环来不断读取用户输入。
在每次循环中,使用`inputReader.ReadString('\n')`读取用户输入。然后使用`strings.Trim(input, "\r\n")`去掉换行符、回车符。
下一步是检查用户输入是否为大写的"Q",如果是的话,退出循环,在此之前关闭连接。
如果不是"Q",则使用`conn.Write()`将用户输入的数据发送到服务器。
然后,使用`conn.Read()`从服务器接收数据,存储在缓冲区`buf`中。读取到的字节数存储在变量`n`中,如果有错误发生,则打印错误信息并返回。
最后,使用`fmt.Println(string(buf[:n]))`打印从服务器接收到的数据。循环会继续,等待用户的下一次输入。
编译为可执行文件
go build -o client.exe
测试一下: