295_尚硅谷_TCP编程快速入门案例分析_哔哩哔哩_bilibili
1.基础客户端处理流程
1)监听端8888
2)接收客户端的tcp链接,建立客户端和服务器端的链接.
3)创建goroutine,处理该链接的请求(通常客户端会通过链接发送请求包)
组件:监听器
代码
package main
import (
"fmt"
"net"
)
func main() {
fmt.Println("服务器开始监听")
//参数 tcp协议, 监听本地8888接口
listen, err := net.Listen("tcp", "0.0.0.0:8888")
/*
type Listener interface {
//Addr返回该接口的网络地址
Addr ( ) Addr
// Aecept等待并返回下一个连接到该接口的连接
Accept()) (c Conn,err error)
//Close关闭该接口,并使任何阳塞的Accept操作都会不再阻塞并返回错误。
Close() error
)
*/
if nil != err {
fmt.Println("监听出错err = ", err)
}
defer listen.Close() //延时关闭监听接口
//循环等待客户端连接
for {
fmt.Println("等待客户端连接 ")
conn, err := listen.Accept() //阻塞等待客户端连接
if nil != err {
fmt.Println("Accept err = ", err)
} else {
fmt.Println("Accept suc,conn = ", conn)
}
}
//fmt.Printf("listen suc=%v", listen)
}
2.基础服务端处理流程
1)建立与服务端的链接
2)发送请求数据[终端],接收服务器端返回的结果数据
3)关闭链接
3.发送数据之后的客户端和服务端
目录结构:
1)客户端
1.首先拨号和服务端建立连接
2.建立一个循环发送信息,每次用Reader从终端接收用户的输入
3.把接收的内容分成byte切片conn.Write()发送给服务端,进入下一次循环
4.输入exit表示退出
package main
import (
"bufio"
"fmt"
"net"
"os"
"strings"
)
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:8888")
if nil != err {
fmt.Println("Dial err = ", err)
}
fmt.Println("conn成功 ", conn)
fmt.Println("开始聊天吧!")
for {
//功能1:客户端发送单行数据
reader := bufio.NewReader(os.Stdin) //os.Stdin代表终端标准输入
//1.从终端读取用户输入
line, err := reader.ReadString('\n')
if nil != err {
fmt.Println("ReadString err = ", err)
}
//如果输入exit代表退出
line = strings.Trim(line, " \r\n") //去掉string里的换行和空格
if "exit" == line {
fmt.Println("客户端退出")
return
}
//2.然后发送line给服务器(要求参数是byte切片,所以转换一下)
n, err := conn.Write([]byte(line + "\n"))
if nil != err {
fmt.Println("conn.Write err = ", err)
}
fmt.Printf("客户端发送了%d字节的数据,并退出\n", n)
}
}
2)服务端
1.建立服务端端口监听器,接收的信息会从这个端口来
2.循环等待客户端连接通过端口发送消息,没有接收到消息那么监听器就阻塞
3.监听器收到消息就会返回一个和客户端的连接
4.建立一个协程专门处理这个客户端的事务
5.协程用一个循环大容量byte切片接收连接传过来的值,conn.Read(buf),
6.如果接收到内容就在服务端输出
7.如果接收或者连接出问题就退出协程
package main
import (
"fmt"
"net"
)
// 协程,处理客户端消息
func process(conn net.Conn) {
//这里我们循环的接收客户端发送的数据
defer conn.Close() //关闭conn
for {
//创建一个新的切片
buf := make([]byte, 1024)
//conn. Read(buf)
//1.等待客户端通过conn发送信息
//2.如果客户端没有wrtie[发送],那么协程就阻塞在这里
fmt.Printf("服务器在等待客户端%s发送信息\n", conn.RemoteAddr().String())
n, err := conn.Read(buf) //从conn读取,等待write操作。n代表从连接里读到内容的长度
if err != nil {
fmt.Println("服务器的Read err=", err)
return //连接有问题就关闭这个处理协程·
}
//3.显示客户端发送的内容到服务器的终端
/*
tips:1.读取的时候已经有换行了,不要Println。
2.需要从byte切片转成string输出,否则是一串数字码
3.注意接收值只到第n个之前,因为我们定义的buf默认是长度1024
*/
fmt.Print(string(buf[:n]))
}
}
func main() {
fmt.Println("服务器开始监听")
//参数 tcp协议, 监听本地8888接口
listen, err := net.Listen("tcp", "0.0.0.0:8888")
/*
type Listener interface {
//Addr返回该接口的网络地址
Addr ( ) Addr
// Aecept等待并返回下一个连接到该接口的连接
Accept()) (c Conn,err error)
//Close关闭该接口,并使任何阳塞的Accept操作都会不再阻塞并返回错误。
Close() error
)
*/
if nil != err {
fmt.Println("监听出错err = ", err)
}
defer listen.Close() //延时关闭监听接口
//循环等待客户端连接
for {
fmt.Println("等待客户端连接 ")
conn, err := listen.Accept() //阻塞等待客户端连接
if nil != err {
fmt.Println("Accept err = ", err)
} else {
fmt.Println("Accept suc,conn = ", conn, "客户端IP", conn.RemoteAddr().String())
}
//准备一个协程,接收客户端消息
go process(conn)
}
//fmt.Printf("listen suc=%v", listen)
}
此时就已经实现了多个客户端向服务器发送消息,接下来就要实现服务器处理消息并发送给对应客户端。