网络分层
OSI七层网络模型 | TCP/IP四层概念模型 | 对应网络协议 | |
---|---|---|
应用层 (Application) | 应用层 | HTTP、TFTP、FTP、NFS、WAIS、SMTP |
表示层(Presentation) | Telnet、Rlogin、SNMP、Gopher | |
会话层 (Session) | SMTP、DNS | |
传输层 (Transport) | 传输层 | TCP、UDP |
网络层 (Network) | 网络层 | IP、ICMP、ARP、RARP、AKP、UUCP |
数据链路层 (Data link) | 数据链路层 | FDDI、Ethernet、Arpanet、PDN、SLIP、PPP |
物理层 (Physical) | IEEE 802.1A、IEEE 802.2到IEEE 802.11 |
socket-client–server通信过程分析
socket-server-单次处理
server DEMO
接收一个链接,而且只能发送一次数据
package main
import (
"fmt"
"net"
"strings"
)
func main() {
//创建监听
ip := "127.0.0.1"
port := 8849
address := fmt.Sprintf("%s:%d", ip,port)
//func Listen(network string, address string) (Listener, error)
listener,err := net.Listen("tcp",address)
//net.Listen("tcp",":8848")//简写,冒号前面默认是本机localhost:127.0.0.1
if err != nil {
fmt.Println("net.Listen err :", err)
return
}
fmt.Println("监听中...")
//func (Listener) Accept() (Conn, error)
conn,err := listener.Accept()
if err != nil {
fmt.Println("listener.Accpet err:",err)
return
}
fmt.Println("链接建立成功")
//创建一个容器,用于j接收读取到的数据
buf := make([]byte,1024)//使用make来创建切片,byte==> uint8
//Read(b []byte) (n int, err error)
//cnt:真正读取client发来的数据的长度,因为用户具体发了多少不知道
cnt, err := conn.Read(buf)
if err != nil {
fmt.Println("conn.Read err:",err)
return
}
fmt.Println("Client ======> server ,长度:", cnt,",数据", string(buf[:cnt]))
//server对client请求进行响应,将数据转换成大写"hello"==>HELLO
//将数据转成大写"hello"==> HELLO
//func ToUpper(s string) string
upperData := strings.ToUpper(string(buf[:cnt]))
//Write(b []byte) (n int, err error)
cnt, err = conn.Write([]byte(upperData))
fmt.Println("Client<=======server ,长度",cnt,",数据:",upperData)
//关闭这个链接
conn.Close()
}
运行结果
tianyi@SPACE-STATION day1 % go run socket-serverdomo.go
监听中...
链接建立成功
Client ======> server ,长度: 10 ,数据 helloworld
Client<=======server ,长度 10 ,数据: HELLOWORLD
```
## client DEMO
````go
package main
import (
"fmt"
"net"
)
func main() {
//func Dial(network, address string) (Conn, error) {
conn, err := net.Dial("tcp",":8849")
if err != nil {
fmt.Println("net.Dial err:", err)
return
}
fmt.Println("client与server链接建立成功!")
sendData := []byte("helloworld")
//向服务器发送数据
cnt, err := conn.Write(sendData)
if err != nil {
fmt.Println("conn.Write err:", err)
return
}
fmt.Println("Client====>server cnt:",cnt,",data:",string(sendData))
//接受服务器返回的数据
//创建buf用于接受server返回的数据
buf := make([]byte,1024)
cnt, err = conn.Read(buf)
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
fmt.Println("Client<=====server,cnt:", cnt,",data", string(buf[:cnt]))
conn.Close()
}
运行结果
tianyi@SPACE-STATION day1 % go run socket-clientdome.go
client与server链接建立成功!
Client====>server cnt: 10 ,data: helloworld
Client<=====server,cnt: 10 ,data HELLOWORLD
socket-client-server 处理多个链接,每个连接可以接收多次数据
server端 主进程用来监听,业务由单独的go func启动
package main
import (
"fmt"
"net"
"strings"
)
func main() {
//创建监听
ip := "127.0.0.1"
port := 8849
address := fmt.Sprintf("%s:%d", ip, port)//通过fmt.Sprintf()将ip:port拼成字符串
//func Listen(network string, address string) (Listener, error)
listener, err := net.Listen("tcp", address)
//net.Listen("tcp",":8848")//简写,冒号前面默认是本机localhost:127.0.0.1
if err != nil {
fmt.Println("net.Listen err :", err)
return
}
//需求:
//server可以接收多个连接,====> 主go程负责监听,子go程负责数据处理
//每个链接可以接收处理多轮数据请求
for {
fmt.Println("监听中...")
//主进程只负责建立连接
//func (Listener) Accept() (Conn, error)
conn, err := listener.Accept()
if err != nil {
fmt.Println("listener.Accpet err:", err)
return
}
fmt.Println("链接建立成功")
go handleFunc(conn)
}
}
//处理具体业务的逻辑,需要将conn传递过来,每一个新的链接,conn是彼此独立的
func handleFunc(conn net.Conn) {
for {//这个for循环,可以保证每一个连接可以多次接受处理客户端请求
//创建一个容器, 用于j接收读取到的数据
buf := make([]byte, 1024) //使用make来创建切片,byte==> uint8
fmt.Println("准备读取客户端发送的数据......")
//Read(b []byte) (n int, err error)
//cnt:真正读取client发来的数据的长度,因为用户具体发了多少不知道
cnt, err := conn.Read(buf)
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
fmt.Println("Client ======> server ,长度:", cnt, ",数据", string(buf[:cnt]))
//server对client请求进行响应,将数据转换成大写"hello"==>HELLO
//将数据转成大写"hello"==> HELLO
//func ToUpper(s string) string
upperData := strings.ToUpper(string(buf[:cnt]))
//Write(b []byte) (n int, err error)
cnt, err = conn.Write([]byte(upperData))
fmt.Println("Client<=======server ,长度", cnt, ",数据:", upperData)
//关闭这个链接 下划线代表忽略这个值,用来接受err
}
_ = conn.Close()
}
client端
package main
import (
"fmt"
"net"
"time"
)
func main() {
//func Dial(network, address string) (Conn, error) {
conn, err := net.Dial("tcp", ":8849")
if err != nil {
fmt.Println("net.Dial err:", err)
return
}
fmt.Println("client与server链接建立成功!")
sendData := []byte("helloworld")
for {
//向服务器发送数据
cnt, err := conn.Write(sendData)
if err != nil {
fmt.Println("conn.Write err:", err)
return
}
fmt.Println("Client====>server cnt:", cnt, ",data:", string(sendData))
//接受服务器返回的数据
//创建buf用于接受server返回的数据
buf := make([]byte, 1024)
cnt, err = conn.Read(buf)
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
fmt.Println("Client<=====server,cnt:", cnt, ",data", string(buf[:cnt]))
time.Sleep(1*time.Second)
}
conn.Close()
}
terminal
1、client
tianyi@SPACE-STATION day1 % go run socket-clientdome.go
client与server链接建立成功!
Client====>server cnt: 10 ,data: helloworld
Client<=====server,cnt: 10 ,data HELLOWORLD
tianyi@SPACE-STATION day1 % go run socket-clientdome.go
client与server链接建立成功!
Client====>server cnt: 10 ,data: helloworld
Client<=====server,cnt: 10 ,data HELLOWORLD
2、server
tianyi@SPACE-STATION day1 % go run socket-server-多链接.go
监听中...
链接建立成功
监听中...
准备读取客户端发送的数据......
Client ======> server ,长度: 10 ,数据 helloworld
Client<=======server ,长度 10 ,数据: HELLOWORLD
准备读取客户端发送的数据......
conn.Read err: EOF
链接建立成功
监听中...
准备读取客户端发送的数据......
Client ======> server ,长度: 10 ,数据 helloworld
Client<=======server ,长度 10 ,数据: HELLOWORLD
准备读取客户端发送的数据......
conn.Read err: EOF
当client多次发送数据时